PHP MySQL Data Insertion from Excel Not Executing as Expected

I have a PHP script that reads data from an Excel file and inserts it into a MySQL database. The script reads the data correctly and performs the initial insertion into the tb_konsultasi table without issues. However, the subsequent insertion into the tb_detailrusak table based on conditions in the Excel data does not execute as expected.

Below is my complete code:

require_once 'includes/connect.php';
require 'vendor/autoload.php';

use PhpOfficePhpSpreadsheetReaderXlsx;

// Mengaktifkan pelaporan error
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

function log_and_echo_error($message) {
    error_log($message);
    echo $message . "<br>";
}

if (!empty($_FILES['file']['name'])) {
    $target_dir = "uploads/";
    $target_file = $target_dir . basename($_FILES["file"]["name"]);

    if (!is_dir($target_dir)) {
        mkdir($target_dir, 0777, true);
    }

    if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_file)) {
        $reader = new Xlsx();
        try {
            $spreadsheet = $reader->load($target_file);
        } catch (Exception $e) {
            log_and_echo_error("Error loading spreadsheet: " . $e->getMessage());
            die("Error loading spreadsheet");
        }
        $sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);

        $koneksi = new mysqli(DATABASE_HOST, DATABASE_USER, DATABASE_PASS, DATABASE_NAME);
        if ($koneksi->connect_error) {
            log_and_echo_error("Connection failed: " . $koneksi->connect_error);
            die("Connection failed: " . $koneksi->connect_error);
        }

        $header = $sheetData[1]; // Simpan header untuk referensi nama atribut
        foreach ($sheetData as $index => $row) {
            if ($index === 1) continue; // skip header row

            if (!empty(array_filter($row))) {
                $tanggal_raw = $row['A'];
                $nama_perangkat = $row['B'];
                $nama_pelanggan = $row['C'];
                $kerusakan = $row['AM']; // Column containing kerusakan information

                // Konversi format tanggal ke YYYY-MM-DD
                $tanggal = date('Y-m-d', strtotime(str_replace('/', '-', $tanggal_raw)));

                // Simpan data konsultasi
                $stmt_konsultasi = $koneksi->prepare("INSERT INTO tb_konsultasi (tanggal, nama_perangkat, nama_pelanggan, hasil_kerusakan) VALUES (?, ?, ?, ?)");
                if (!$stmt_konsultasi) {
                    log_and_echo_error("Prepare failed for konsultasi: " . $koneksi->error);
                    continue;
                }
                $stmt_konsultasi->bind_param("ssss", $tanggal, $nama_perangkat, $nama_pelanggan, $kerusakan);
                if (!$stmt_konsultasi->execute()) {
                    log_and_echo_error("Execute failed for konsultasi: " . $stmt_konsultasi->error);
                    continue;
                }
                $id_konsultasi = $stmt_konsultasi->insert_id;
                $stmt_konsultasi->close();

                // Simpan detail kerusakan berdasarkan gejala
                foreach ($row as $key => $value) {
                    if ($key > 'C' && $key < 'AK' && $value == 'Ya') {
                        $nama_atribut = $header[$key]; // Ambil nama atribut dari header
                        $stmt_atribut = $koneksi->prepare("SELECT id_atribut FROM tb_atribut WHERE nama_atribut = ?");
                        if (!$stmt_atribut) {
                            log_and_echo_error("Prepare failed for atribut: " . $koneksi->error);
                            continue;
                        }
                        $stmt_atribut->bind_param("s", $nama_atribut);
                        if (!$stmt_atribut->execute()) {
                            log_and_echo_error("Execute failed for atribut: " . $stmt_atribut->error);
                            continue;
                        }
                        $result_atribut = $stmt_atribut->get_result();
                        if ($result_atribut->num_rows > 0) {
                            $atribut = $result_atribut->fetch_assoc();
                            $id_atribut = $atribut['id_atribut'];
                            $stmt_detail = $koneksi->prepare("INSERT INTO tb_detailrusak (id_konsultasi, id_atribut) VALUES (?, ?)");
                            if (!$stmt_detail) {
                                log_and_echo_error("Prepare failed for detailrusak: " . $koneksi->error);
                                continue;
                            }
                            $stmt_detail->bind_param("ii", $id_konsultasi, $id_atribut);
                            if (!$stmt_detail->execute()) {
                                log_and_echo_error("Execute failed for detailrusak: " . $stmt_detail->error);
                                continue;
                            }
                            $stmt_detail->close();
                        } else {
                            log_and_echo_error("Atribut not found: " . $nama_atribut);
                        }
                        $stmt_atribut->close();
                    }
                }
            }
        }
        $koneksi->close();
        echo json_encode(array(
            'status' => 'Success',
            'message' => 'Data berhasil diimpor!'
        ));
    } else {
        log_and_echo_error("Failed to move uploaded file.");
        echo json_encode(array(
            'status' => 'Error',
            'message' => 'Failed to move uploaded file.'
        ));
    }
} else {
    log_and_echo_error("No file selected.");
    echo json_encode(array(
        'status' => 'Error',
        'message' => 'No file selected'
    ));
}

Issues:

The initial insertion into tb_konsultasi works fine.
The subsequent insertion into tb_detailrusak based on specific conditions does not work as expected.

**What I have tried:
**
Added error logging and echo statements to debug the issue.
Verified that the conditions for inserting into tb_detailrusak are met.
Ensured that the database connection is successful and the initial insertion into tb_konsultasi works.
Checked if tb_atribut contains the relevant data for nama_atribut.

Database Schema:

tb_konsultasi: id_konsultasi (AUTO_INCREMENT, PRIMARY KEY), tanggal, nama_perangkat, nama_pelanggan, hasil_kerusakan
tb_detailrusak: id_detailrusak (AUTO_INCREMENT, PRIMARY KEY), id_konsultasi, id_atribut
tb_atribut: id_atribut (AUTO_INCREMENT, PRIMARY KEY), nama_atribut

Questions

Why isn’t the insertion into tb_detailrusak executing as expected even when the conditions are met?
Are there any improvements or debugging steps I might be missing to resolve this issue?
Any help or insights would be greatly appreciated!

Laravel resource collection, how do you correctly format data for blade

I have a model, let’s say this a Task model. It has title, description, and status_id.

I want to make a resource model to format the status, so the frontend (just a simple blade) can use it.

So, I made a resource collection, like this:

class TaskResource extends JsonResource
{
    public function toArray(Request $request): object
    {
        return (object) [
            'id' => $this->id,
            'title' => $this->title,
            'description' => $this->description,
            'status' => (object) [
                'id' => $this->status_id,
                'display' => TaskStatus::tryFrom($this->status_id)?->text(),
            ],
        ];
    }
}

… and I do this in my controller

    public function show(Task $task)
    {
        return view('tasks.show', ['task' => new TaskResource($task)]);
    }

So, I can access $task in my blade – but the problem is, status, nor the id inside status are accessible. Like they don’t exist. Even if I do something like this:

            'title' => $this->title,
            'random' => $this->title,

then $task->title returns the title, but $task->random will show nothing.

I do not want to call ->toArray(request()) everywhere, every single time on the new resource, also there’s no reason for me to pass the request every single time (tho I can’t update it to not make it required, because of the built-in interface).

I also don’t want to use laravel magic, like “getStatusDisplayAttribute” and such, because laravel magic is for sure useful, but is hard to maintain on a larger scale.

A “workaround” I found as a possible solution is resolve, which works with both TaskResource::collection and (new TaskResource()).

return view('tasks.show', ['task' => (new TaskResource($task))->resolve()]);

But is this a good practice? Or there’s a different way people format the data as needed on the backend, before passing it to the frontend?

I want to make sure I don’t make many bad decisions while learning.

How to update JSON base on it’s text version?

We’re a video streaming platform (e.g. FlixNet). A video has separate audio files in different languages and also subtitles for each audio file. We get the subtitles from the vendor as a plain text. Using AI we convert that plain text into JSON. Each items in it represents a time frame (start, end in seconds from the start of the audio file) and the subtitle itself. Here is an example:

“Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam id
consectetur tellus, a malesuada lacus. Donec dignissim ornare
fringilla. Integer sed lorem vel mi dictum tempus vel et lorem. Sed
aliquam volutpat sem. Cras quam nulla, laoreet vitae leo cursus,
laoreet facilisis sapien. Aliquam vitae”

{
  "transcription": [
    {
      "start": 3,
      "end": 5,
      "text": "Lorem ipsum dolor sit amet,"
    },

    {
      "start": 6,
      "end": 7,
      "text": "consectetur adipiscing elit."
    },
    {
      "start": 8,
      "end": 10,
      "text": "Nam id consectetur tellus, a malesuada lacus."
    },
    {
      "start": 15,
      "end": 17,
      "text": "Donec dignissim ornare fringilla."
    },
    {
      "start": 19,
      "end": 22,
      "text": "Integer sed lorem vel mi dictum tempus vel et lorem."
    },
    {
      "start": 23,
      "end": 24,
      "text": "Sed aliquam volutpat sem. Cras quam nulla,"
    },
    {
      "start": 25,
      "end": 26,
      "text": "laoreet vitae leo cursus, laoreet"
    },
    {
      "start": 29,
      "end": 30,
      "text": "facilisis sapien. Aliquam vitae"
    }
  ]
}

Time frames have different length and may have gaps when no one is talking. I don’t know the pattern by which AI chops text into JSON.
The issues:
vendor may send us updated subtitles. For example: changed translation, fixed typos or removed entire paragraph because it’s rasist or 18+.
We’re using PHP 7.2. I need to write some php script that can identify the changes and update the subtitle in the JSON without triggering the AI again, because it costs money and sometimes AI hallucinating.

Install ext-ftp extension using the official docker image

I am trying to install the php ftp extension without any luck. I am using the official docker PHP image. I am re-building the image with docker compose build --no-cache

I’ve also tried RUN docker-php-ext-enable ftp

FROM php:8.3-fpm

WORKDIR /var/www/html

RUN docker-php-ext-install ftp

php -m

[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
hash
iconv
intl
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
random
readline
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
tokenizer
xdebug
xml
xmlreader
xmlwriter
zip
zlib

[Zend Modules]
Xdebug

Get class from constant

I have a function with a parameter that is fed a constant.
The constant can come from several classes, see example:

function myFunction($const): string {
    // do some stuff
    // use the classname do some other stuff
    // do some more stuff

    return $output;
}

echo myFunction(SomeClass::A_CONSTANT);
echo myFunction(OtherClass::ALSO_A_CONSTANT);

To make things more difficult, the constants I’m getting come from aliased classes, in the class file outside the class you have something like this:

class_alias(RealClass::class, 'SomeClass');

Is there a way to get the classname from the constant?
So from the example above I would get RealClass when I use the constant SomeClass::A_CONSTANT.
I can work around the alias, getting SomeClass when I use SomeClass::A_CONSTANT is just fine.

I’ve tried get_defined_constants(), get_class(), get_parent_class() & get_called_class(), but those just get the result or result in errors due to not being in scope or the variable being a string instead of an object.

How to apply generics correctly to PHP?

Background

I do have classes (here: ClassA and ClassB) that shall be tested. As these classes are similar, I created an abstract test-class that implements an interface.

Problem

At level 7, PhpStan is unhappy and reports these issues:

  • Call to an undefined method object::getId()
  • Call to an undefined method object::getName()

I do know that it is unclear which object is calling the methods and thus the issue is reported and I know that the solution is by using GENERICS.

Question

I just started with the use of generics, I have no clue how to solve this correctly.
Anybody so kind to support me here? Thanks!

Code

see PhpStan Playground.

REMARK: The example here is simplified to support the discussion.

<?php

// ---------------------------------------- CLASSES
class ClassA {
    public function getId(): int {
        return 123;
    }
}
class ClassB {
    public function getName(): string {
        return 'abc';
    }
}

// ---------------------------------------- TESTS

/**
 * @template T
 */
interface InterfaceForTest {
    public function getClassName(): string; 
}

/**
 * @template T
 * @implements InterfaceForTest<T>
 */
abstract class AbstractClassTest implements InterfaceForTest {
    public function createObject(): object
    {
        $class  = $this->getClassName();
        $object = new $class();
        return $object;
    }
}

/**
 * @template T
 * @extends AbstractClassTest<T>
 */
class ClassATest extends AbstractClassTest {
    public function getClassName(): string
    {
        return ClassA::class;
    }

    public function testA(): void
    {
        $obj = $this->createObject();

        assert($obj->getId() === 123);      // makes PHPStan unhappy at level 7
    }
}

/**
 * @template T
 * @extends AbstractClassTest<T>
 */
class ClassBTest extends AbstractClassTest {
    public function getClassName(): string
    {
        return ClassB::class;
    }

    public function testA(): void
    {
        $obj = $this->createObject();
        
        assert($obj->getName() === 'abc');  // makes PHPStan unhappy at level 7
    }
}

add parameters to an Artisan cronjob

Sorry in advance, I’m an .net developer, so PhP is something I’m not really familiar with.

Our hosting provider only have the ability to run cronjobs through calling a webpage.
We have a cronjob that needs an argument “schedule:run”.

I found the article on which this particular script is based on.
https://dev.to/obasekietinosa/deep-dive-into-the-laravel-artisan-file-3nge

While reading the documentation (https://peridot-php.github.io/docs/class-Symfony.Component.Console.Input.ArgvInput.html), I found out that you can pass arguments by declaring an own $input variable, like

$input = new ArgvInput($_SERVER['argv'])

Is my understanding correct if I add the argument to the array, that whis should work?

$input = new ArgvInput($_SERVER['argv', 'schedule:run'])

So the call would be:

$status = $kernel->handle(
    #$input = new SymfonyComponentConsoleInputArgvInput,
    $input = new ArgvInput($_SERVER['argv','schedule:run']),
    new SymfonyComponentConsoleOutputConsoleOutput
);

crypt() function behavior – is that a php bug?

working with crypt() function, I can observe that :

$var1 = crypt('rasmuslerdorf', 'cd');
$var2 = crypt('rasmuslerdorfWhatever', 'cd');

generates exactly the same output ! Here : cdqYxeZGYiRPw

You can try by yourself online : https://fr.functions-online.com/crypt.html

From the doc I can read about the maximum length of the resulting string, but nothing about the input string !

Returns the hashed string or a string that is shorter than 13 characters and is guaranteed to differ from the salt on failure.

Is that a normal behavior ? I don’t think so.

I’m using PHP Version 8.1.2

React Native with Expo, PHP WebSocket connection

I am developing a mobile application and I would like to send notifications to the relevant users when there is a change in a database table. To achieve this, I have tried to create a WebSocket server that listens to the database and notifies the frontend, which then sends notifications even when the application is closed. However, my frontend is unable to connect to the WebSocket server. Here is the error:

LOG WebSocket error: {“isTrusted”: false, “message”: “The operation couldn’t be completed. Connection refused”}
LOG WebSocket is closed.

I am new to mobile development and I have never created a socket server before.

<?php
require __DIR__ . '/vendor/autoload.php';

use RatchetMessageComponentInterface;
use RatchetConnectionInterface;
use ReactEventLoopLoop;
use RatchetApp;

class DatabaseWatcher implements MessageComponentInterface
{
    protected $clients;
    protected $lastMaxId;

    public function __construct()
    {
        $this->clients = new SplObjectStorage;
        $this->lastMaxId = $this->getMaxId(); 
    }

    public function onOpen(ConnectionInterface $conn)
    {
        $this->clients->attach($conn, ['ref_restaurant' => null]);
        echo "New connection! ({$conn->resourceId})n";
    }

    public function onMessage(ConnectionInterface $from, $msg)
    {
        
        $data = json_decode($msg, true);
        if (isset($data['ref_restaurant'])) {
            $this->clients[$from]['ref_restaurant'] = $data['ref_restaurant'];
            echo "Client {$from->resourceId} set ref_restaurant to {$data['ref_restaurant']}n";
        }
    }

    public function onClose(ConnectionInterface $conn)
    {
        $this->clients->detach($conn);
        echo "Connection {$conn->resourceId} has disconnectedn";
    }

    public function onError(ConnectionInterface $conn, Exception $e)
    {
        echo "An error has occurred: {$e->getMessage()}n";
        $conn->close();
    }

    public function getMaxId()
    {
        try {
            $pdo = new PDO('mysql:host=193.203.168.77;dbname=u440859155_db_yumeats', 'u440859155_yumeats', 'YumEats2024@');
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

            $stmt = $pdo->query('SELECT MAX(id) AS max_id FROM orders');
            $result = $stmt->fetch(PDO::FETCH_ASSOC);

            return $result['max_id'] ?? 0;
        } catch (PDOException $e) {
            echo "Database error: " . $e->getMessage() . "n";
            return 0;
        }
    }

    public function checkDatabase()
    {
        try {
            $pdo = new PDO('mysql:host=193.203.168.77;dbname=u440859155_db_yumeats', 'u440859155_yumeats', 'YumEats2024@');
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

            $stmt = $pdo->prepare('SELECT * FROM orders WHERE id > :lastMaxId');
            $stmt->execute(['lastMaxId' => $this->lastMaxId]);
            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

            if (!empty($rows)) {
                $this->lastMaxId = max(array_column($rows, 'id'));
                echo "New entries found:n";
                print_r($rows); // Log the new entries
                foreach ($this->clients as $client) {
                    $clientRestaurant = $this->clients[$client]['ref_restaurant'];
                    $filteredRows = array_filter($rows, function ($row) use ($clientRestaurant) {
                        return $row['ref_restaurant'] === $clientRestaurant;
                    });

                    if (!empty($filteredRows)) {
                        $client->send(json_encode($filteredRows));
                    }
                }
            }
        } catch (PDOException $e) {
            echo "Database error: " . $e->getMessage() . "n";
        }
    }
}

$app = new RatchetApp('0.0.0.0', 8080);
$loop = Loop::get();

$databaseWatcher = new DatabaseWatcher();
$loop->addPeriodicTimer(1, function () use ($databaseWatcher) {
    $databaseWatcher->checkDatabase();
});

$app->route('/database-watcher', $databaseWatcher, ['*']);
$app->run();

const ws = useRef(null); 

const initializeWebSocket = (refRestaurant) => {
    ws.current = new WebSocket('ws://localhost:8080/database-watcher');
    
    ws.current.onopen = () => {
        console.log('WebSocket is connected.');
        ws.current.send(JSON.stringify({ ref_restaurant: refRestaurant }));
    };
    
    ws.current.onmessage = (event) => {
        const data = JSON.parse(event.data);
        console.log('Received data:', data);
        setOrdersAndClients(prevOrders => [...prevOrders, ...data]); 


        Alert.alert(
            "Nouvelle commande",
            "Une nouvelle commande a été reçue.",
            [{ text: "OK" }]
        );
    };
    
    ws.current.onclose = () => {
        console.log('WebSocket is closed.');
    };
    
    ws.current.onerror = (error) => {
        console.log('WebSocket error:', error);
    };
};

Codeigniter 3 email not sent in CLI mode

I have a task setup as a controller index function. If I call the controller directly from browser as localhost://app/cron the emails go out normally and arrive in my inbox. But when I call it from CLI as path/to/php path/to/index.php cron everything looks normal, no error is thrown in log files or on screen but emails are not delivered.

Even the following hack also outputs no error text.

if($this->CI->email->send()){
    echo 'Email sent to '.$email;
}else{
    echo 'Error sending email to '.$email;
}

Why are there no custom notifications Buddypress?

I created a small plugin where users can subscribe to authors, but for some reason users are not notified when the author publishes a new post. Please help to solve this problem. I checked the logs, it shows that the notification was sent, but the notification itself is not there!

<?php
/*
Plugin Name: Author Subscription and Notification
Description: Allows users to subscribe to authors and receive notifications when authors publish new posts.
Version: 1.3
Author: test
*/

// Hook to create the database table upon plugin activation
register_activation_hook(__FILE__, 'create_subscriptions_table');

function create_subscriptions_table() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'author_subscriptions';
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE $table_name (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        user_id bigint(20) NOT NULL,
        author_id bigint(20) NOT NULL,
        PRIMARY KEY (id),
        UNIQUE KEY user_author (user_id, author_id)
    ) $charset_collate;";

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
}

// Hook to add subscription button in the post content
add_filter('the_content', 'add_author_subscription_button_to_post');

function add_author_subscription_button_to_post($content) {
    if (is_single() && is_user_logged_in()) {
        $author_id = get_the_author_meta('ID');
        $current_user_id = get_current_user_id();
        
        global $wpdb;
        $table_name = $wpdb->prefix . 'author_subscriptions';

        // Check if user is already subscribed
        $is_subscribed = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM $table_name WHERE user_id = %d AND author_id = %d",
            $current_user_id, $author_id
        ));

        $button_text = $is_subscribed ? 'Unsubscribe' : 'Subscribe';
        $button_html = '<button id="subscribe-author" class="subscribe-button" data-author-id="' . esc_attr($author_id) . '">' . esc_html($button_text) . '</button>';
        $button_html .= '<div id="subscription-message"></div>';
        
        $content .= $button_html;
    }
    return $content;
}

// Enqueue the JavaScript file and localize script
add_action('wp_enqueue_scripts', 'enqueue_subscription_script');

function enqueue_subscription_script() {
    if (is_single() && is_user_logged_in()) {
        wp_enqueue_script('subscription-script', plugin_dir_url(__FILE__) . 'subscription.js', array('jquery'), '1.0', true);
        wp_localize_script('subscription-script', 'subscriptionData', array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce'    => wp_create_nonce('subscription_nonce')
        ));
    }
}

// Handle the AJAX request for subscription
add_action('wp_ajax_handle_author_subscription', 'handle_author_subscription');

function handle_author_subscription() {
    check_ajax_referer('subscription_nonce', 'nonce');

    if (is_user_logged_in()) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'author_subscriptions';

        $current_user_id = get_current_user_id();
        $author_id = intval($_POST['author_id']);
        $operation = sanitize_text_field($_POST['operation']);
        
        if ($operation === 'subscribe') {
            $wpdb->insert($table_name, array(
                'user_id' => $current_user_id,
                'author_id' => $author_id
            ));
            wp_send_json_success('Subscribed successfully.');
            error_log("User ID $current_user_id subscribed to author ID $author_id");
        } else if ($operation === 'unsubscribe') {
            $wpdb->delete($table_name, array(
                'user_id' => $current_user_id,
                'author_id' => $author_id
            ));
            wp_send_json_success('Unsubscribed successfully.');
            error_log("User ID $current_user_id unsubscribed from author ID $author_id");
        }
    }
    wp_send_json_error('Failed to update subscription.');
}

// Hook to send notifications when an author publishes a new post
add_action('publish_post', 'notify_subscribers_on_new_post');

function notify_subscribers_on_new_post($post_id) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'author_subscriptions';

    $post = get_post($post_id);
    $author_id = $post->post_author;

    error_log("New post published by author ID: " . $author_id);

    // Get subscribers
    $subscribers = $wpdb->get_results($wpdb->prepare(
        "SELECT user_id FROM $table_name WHERE author_id = %d",
        $author_id
    ));

    error_log("Subscribers found: " . count($subscribers));

    foreach ($subscribers as $subscriber) {
        // Send BuddyPress notification
        bp_notifications_add_notification(array(
            'user_id'           => $subscriber->user_id,
            'item_id'           => $post_id,
            'secondary_item_id' => $author_id,
            'component_name'    => 'buddypress',
            'component_action'  => 'new_post_by_subscribed_author',
            'date_notified'     => bp_core_current_time(),
            'is_new'            => true,
        ));
        error_log("Notification sent to user ID: " . $subscriber->user_id);
    }
}

// Custom notification format
add_filter('bp_notifications_get_notifications_for_user', 'custom_bp_notification_format', 10, 5);

function custom_bp_notification_format($content, $item_id, $secondary_item_id, $action, $component_name) {
    if ($component_name === 'buddypress' && $action === 'new_post_by_subscribed_author') {
        $author_name = get_the_author_meta('display_name', $secondary_item_id);
        $post_title = get_the_title($item_id);
        $post_url = get_permalink($item_id);
        
        $content = sprintf(__('New post by %s: <a href="%s">%s</a>', 'text-domain'), $author_name, $post_url, $post_title);
    }
    
    return $content;
}
?>

Here is the log itself!

[23-May-2024 09:42:15 UTC] a:0:{}
[23-May-2024 09:42:40 UTC] New post published by author ID: 1
[23-May-2024 09:42:40 UTC] Subscribers found: 2
[23-May-2024 09:42:40 UTC] Notification sent to user ID: 1
[23-May-2024 09:42:40 UTC] Notification sent to user ID: 27
[23-May-2024 09:42:43 UTC] a:0:{}

How to modify the Request URL in Drupal 8.9 search when selecting a Facet?

I’m working on a Drupal 8.9 site and I’m using the Facet module to add facets to my search. I need to modify the request URL dynamically when a user selects a facet, specifically to add or alter query parameters in the URL based on the selected facets.

To achieve my goal, I’ve created a custom UrlProcessor.

The most important aspect is that when the URL changes and the search results page is reloaded, it should retain the same results as before the modification. I’ve tried different methods, but with all of them, when navigating to the new URL, there are no search results because the modification occurs after the indexing.

Has anyone done this before or could point me in the right direction? Any help or code examples would be greatly appreciated!

Thanks in advance!

What I’ve Tried:

Creating patches for the URL processor of the Facet module.
Modifying the URL in the RouteSubscriber of the module.
Using the PathProcessor in a custom module through the InboundPathProcessorInterface.
With all these methods, I’ve managed to modify the URL, but the new URL doesn’t return results because the modification happens after the indexing.

What I Hope to Achieve:

I want to modify the Request URL using my custom UrlProcessor while retaining the search results that would be obtained without the modifications.