Laravel Upgradation issue

While upgrading laravel from 6.2 to 7 this error occurs.
My current php version: 7.2.34

Fatal error: Uncaught Error: Class ‘Auth’ not found in /opt/lampp/htdocs/localApp/app/Exceptions/Handler.php:40

Enable custom taxonomy and product_tag in WooCommerce product search

I’m hoping that one of you geniuses can help me.

I have a site: https://lifesourcebookshop.co.uk/ that I want to modify the WooCommerce product search on.

What I want: To modify the query of the WooCommerce search form (in frontend) to display the products by searching in the name, description, product_tag and a custom taxonomy called book_author of the products.

What I have: I’ve tried with this code inspired from this answer that returns results for the name and description of the product. But if I search with the tag names or the book author, then the results aren’t correct.

How to reproduce this issue (put the code below in functions.php file of your active theme):

add_filter('posts_search', 'woocommerce_search_product_tag_extended', 999, 2);
function woocommerce_search_product_tag_extended($search, $query) {
    global $wpdb, $wp;
    $qvars = $wp->query_vars;
    if (is_admin() || empty($search) ||  !(isset($qvars['s']) && isset($qvars['post_type']) && !empty($qvars['s']) && $qvars['post_type'] === 'product')) {
        return $search;
    }
    $taxonomies = array('product_tag', 'book_author');
    $tax_query  = array('relation' => 'OR');
    foreach($taxonomies as $taxonomy) {
        $tax_query[] = array(
            'taxonomy' => $taxonomy,
            'field'    => 'name',
            'terms'    => esc_attr($qvars['s']),
        );
    }
    $ids = get_posts(array(
        'posts_per_page'  => -1,
        'post_type'       => 'product',
        'post_status'     => 'publish',
        'fields'          => 'ids',
        'tax_query'       => $tax_query,
    ));
    if (sizeof($ids) > 0) {
        $search = str_replace('AND (((', "AND ((({$wpdb->posts}.ID IN (" . implode( ',', $ids ) . ")) OR (", $search);
    }
    return $search;
}

Example: If you search for murphy (an author) – https://lifesourcebookshop.co.uk/?s=murphy&post_type=product then it only shows 2 products. However, if I look at the archive for that author (https://lifesourcebookshop.co.uk/book_author/abigail-murphy/), then there are actually 5 books.

I’m hoping you can help.

Thanks,
Rob

Deprecation notice for “dynamic properties” in PHP 8.3 in spite of documented exemption / workaround?

As of PHP 8.2, “dynamic properties” have been deprecated and will be removed in PHP 9.0, see https://php.watch/versions/8.2
Before refactoring dynamic properties into a WeakMap, there are supposed to be a few exemptions from the deprecation (cf. the above link), and one of these exemptions are classes with __getand __set magic methods. And indeed, while on PHP 8.2, my code produced no deprecation notice.

However, it seems that after upgrade to PHP 8.3, the deprecation notice is issued in the body of the following, i.e., in the very implementation of those exempting magics:

 public function __set($property_name, $value)
 {
    $this->$property_name = $value;
 }

On https://php.watch/versions/8.3 and https://www.php.net/releases/8.3/en.php , I find no hints that the exemption was removed.

Question: Is this a negligience in the PHP 8.3 documentation, or am I missing some reason why “my” __set(and similar __get) are not good enough to count for the exemption?

(Meanwhile, I added the #[AllowDynamicProperties] to the class, but am still curious)

Generate PDF with placeholders [closed]

I’m looking for a method to generate a PDF in Laravel that has placeholders in it. I have found a lot of information about parsing existing documents and filling in the placeholders but can’t find anything about how to generate a PDF with placeholders in it.

The use case for this is the ability to programatically create a PDF that can be then sent to a third part signing agent (such as DocuSign) to be digitally signed and sent back. The third party we’re working with requires a placeholder to be created (named “ParsingIdentifer”) that their software can then read.

I have found instructions on how to create a placeholder using something like Microsoft Word, but I can’t find any way to generate this PDF using code.

I’ve looked into Laravel libraries for DomPdf and FPDF but neither of these has a clear way of adding in Placeholders.

How to make Xdebug (v3) work with VSCode and Docker (or Podman) on a Windows host?

When I use Xdebug with VSCode (and the PHP Debug extension) locally on my Windows host, it works fine.
But when I try to use Xdebug on a docker/podman container, it doesn’t work – it won’t stop on breakpoints, even though the connection is succesful.

This is my Dockerfile:

# Use official PHP image with FPM and CLI
FROM php:8.2-fpm

# Install system dependencies and PHP extensions for Laravel
RUN apt-get update && apt-get install -y 
    git 
    unzip 
    libpq-dev 
    libonig-dev 
    libxml2-dev 
    libzip-dev 
    && docker-php-ext-install pdo pdo_mysql pdo_pgsql zip mbstring xml

# Install Xdebug
RUN pecl install xdebug && docker-php-ext-enable xdebug

# Configure Xdebug
RUN echo "zend_extension=xdebug.so" >> /usr/local/etc/php/php.ini 
    && echo "xdebug.mode=debug" >> /usr/local/etc/php/php.ini 
    && echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/php.ini 
    && echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/php.ini 
    && echo "xdebug.client_port=9003" >> /usr/local/etc/php/php.ini 
    && echo "xdebug.remote_port=9003" >> /usr/local/etc/php/php.ini 
    && echo "xdebug.log=/tmp/xdebug.log" >> /usr/local/etc/php/php.ini  
    && echo "xdebug.idekey=VSCODE" >> /usr/local/etc/php/php.ini 

# Install Composer globally
COPY --from=composer:2.4 /usr/bin/composer /usr/bin/composer

# Set the working directory to /var/www
WORKDIR /var/www

# Copy the Laravel project to the container
COPY . .

# Install Laravel dependencies
RUN composer install --no-interaction --prefer-dist --optimize-autoloader

# Set permissions for storage and cache
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache

# Expose port 8000 for Laravel's Artisan serve
EXPOSE 8000

# Start the Laravel development server
CMD php artisan serve --host=0.0.0.0 --port=8000

And this is how I build and run the container:

podman build . -t=xdebug

podman run -d -p 8000:8000 -p 9003:9003 xdebug

The output of xdebug_info() shows that the connection is successful and no errors.

I read somewhere that it might have to do with pathMappings: https://github.com/xdebug/vscode-php-debug/issues/653#issuecomment-919385770

Though I tried a few options and it still didn’t work (Maybe the issue is related to pathMappings, but couldn’t make it work still. What should my values be in this case? It’s a Laravel project if that matters)

What is the posibility for Str::random to create same string upon each app isntance in multi-server webapp?

I am making this model in my laravel Application.


namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
use IlluminateSupportStr;

class ApiKeys extends Model
{
    use HasFactory;

    const TABLE = 'api_keys';
    protected $table = self::TABLE;

    public static function boot()
    {
        parent::boot();

        self::creating(function ($model) {
            $model->identifier = Str::random(16);
        });
    }
}

And upon Identifier I want to ensure that contains a unique random string:


use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('api_keys', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('identifier')->unique('unique_identifier');
            $table->boolean('active');
            $table->timestamps();

        });
    }

    public function down(): void
    {
        Schema::dropIfExists('api_keys');
    }
};

But my application runs in multiple instances behind load balancer:

enter image description here

Would this cause not unique random strings be generated, in other words could Str::random(16) (and the underlying function openssl_random_bytes) generate non unique string if both executed from multiple instances?

In order to avoid this usually I prepend the hostname:

  $model->identifier = gethostname()."_".Str::random(16);

But this makes the identifier look ugly or even expose some infrastructure information. How I could avoid this?

Custom product type – add Product to WooCommerce Cart

I am trying to add my product to cart.
I have created product type bookable_product. So when I executed below code

function add_bookable_product_to_cart()
{
   if (! is_admin()) {
      $product_id = 38; // Your bookable product ID
      $product_cart_id = WC()->cart->generate_cart_id($product_id);

      if (! WC()->cart->find_product_in_cart($product_cart_id)) {
         // Add the bookable product to the cart
         $added = WC()->cart->add_to_cart($product_id);

         if (!$added) {
            // Handle failure to add, maybe log or display an error
            error_log('Could not add product to cart: ' . $product_id);
         }
      }
   }
}
add_action("wp", "add_bookable_product_to_cart", 10);

As per this doc

I have used WooCommerce for only product management purpose all fields I have created my self. So in default product I have not added any data of WC.

Stripe: default payment method not retrievable via API

With the Stripe API, I’m trying to retrieve the default payment method of a customer via first via the subscription, then via the customer profile. Like so:

try {
            $subscription = StripeSubscription::retrieve($subscriptionId);
            $defaultPaymentMethodId = $subscription->default_payment_method;

            if (empty($defaultPaymentMethodId)) {
                $customer = StripeCustomer::retrieve($customerId);
                $defaultPaymentMethodId = $customer->invoice_settings->default_payment_method;
            }

            if (!empty($defaultPaymentMethodId)) {
                $paymentMethod = StripePaymentMethod::retrieve($defaultPaymentMethodId);
                $last4 = $paymentMethod->card->last4;
                $exp_year = $paymentMethod->card->exp_year;
                $exp_month = sprintf("%02d", $paymentMethod->card->exp_month);
                $brand = ucwords($paymentMethod->card->brand);
                $has_payment_method = true; // Set to true if a payment method is found
            } else {
                $last4 = $exp_year = $exp_month = $brand = null; // Set these to null to avoid potential issues
            }
        } catch (Exception $e) {
            logError('Stripe API error trying to get payment method details: ' . $e->getMessage());
        }

In both cases, I’m getting a ‘null’ result, even though I can see in the Stripe dashboard that the customer has, in fact, a default payment method set: (I only accept cards, so it has to be a card)

screenshot from the dashboard

I have tried all sort of trouble shooting. API works fine for other work, I can retrieve all the other info of customers, just not the default payment method.

Any ideas what else I could try?

How to use ESLint 9.11 with PHP?

Previously, I used .eslintrc.json setting with ESLint, using the eslint-plugin-html and the eslint-plugin-php-markup plugins to work through the PHP code. Here’s my previous setting:

{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": "eslint:recommended",
  "overrides": [
  ],
  "parserOptions": {
    "ecmaVersion": "latest"
  },
  "rules": {
    "no-redeclare": "warn",
    "no-unused-vars": "warn",
    "no-redeclare": "warn",
    "no-extra-semi": "off",
    "no-empty": "off",
    "no-inner-declarations": "off",
    "no-useless-escape": "off"
  },
  "plugins": [ "html", "php-markup" ],
  "settings": {
    "php": {
      "php-extensions": [ ".php" ],
      "markup-replacement": { "php": "", "=": "0" },
      "keep-eol": false,
      "remove-whitespace": false,
      "remove-empty-line": false,
      "remove-php-lint": false
    }
  }
}

Now that I’ve upgraded to ESLint 9.11, the setting was automatically migrated to eslint.config.mjs, here’s my new settings:

import html from "eslint-plugin-html";
import phpMarkup from "eslint-plugin-php-markup";
import globals from "globals";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
    baseDirectory: __dirname,
    recommendedConfig: js.configs.recommended,
    allConfig: js.configs.all
});

export default [...compat.extends("eslint:recommended"), {
    plugins: {
        html,
        "php-markup": phpMarkup,
    },

    files: ["**/*.{php,js,html,htm}"],

    languageOptions: {
        globals: {
            ...globals.browser,
        },

        ecmaVersion: "latest",
        sourceType: "script",
    },

    settings: {
        "php-markup": {
            "php-extensions": [".php"],

            "markup-replacement": {
                php: "",
                "=": "0",
            },

            "keep-eol": false,
            "remove-whitespace": false,
            "remove-empty-line": false,
            "remove-php-lint": false,
        },
    },

    rules: {
        "no-redeclare": "warn",
        "no-unused-vars": "warn",
        "no-extra-semi": "off",
        "no-empty": "off",
        "no-inner-declarations": "off",
        "no-useless-escape": "off",
    },
}];

However, I can no longer lint my PHP files anymore. With the existing settings, ESLint just throw up valid JS-embedded PHP constructs as syntax errors.

How can I make PHP work with ESLint 9.11?

Why mt_rand is not a good option?

I am creating an exericse for my users, where I am trying to tell them that using mt_rand() is not a good option from security point of view. What I did is that I showed them a normal user who gets a password reset email, the token is generated like this

 mt_srand(ip2long( crc32($email));
        $random_number = mt_rand();

Now I tell them once the user gets the token, we can reverse engineer it easily using https://www.openwall.com/php_mt_seed/, which would allow us to get the seed value for any randomly genrated value. My aim here is to show them if we get the seed, it would allow us to get access of admin token, or some catastrophic effect. but seems like getting the seed here is useless.

If the admin tries to reset his password, he will be using different email, thus a different seeding number and different random number. If I only have access to admin’s email, how can I show my audience the catastrophic effect of mt_rand using the same scenario?

Laravel 11: Basic Auth to protect & showcase unfinished app to Client

I have an app that is still under development, yet it is already deployed and live on the server. To protect it from being visited by boots or humans who should not see it yet, I have enabled Basic Auth via server provisioning dashboard (I use runcloud) not Laravel itself.

This all works fine, but because the app integrates payments I had to implement POST route (webhook) for external payment provider to hit it whenever it has to confirm payment. This single route should not be behind basic auth, otherwise payment provider is getting HTTP 401.

So I have:

  1. disabled basic auth on the provisioning dashboard
  2. enabled basic auth on Laravel level by adding auth.basic middleware to all my routes except the webhook one.
    Route::post('/payments/verify', [PaymentsController::class, 'verify'])
        ->name('payments.verify')
        ->withoutMiddleware('auth.basic');

This also works but by default, Laravel will use email and password from users table for credentials. I don’t want this. I want a fixed & simple credentials for everyone like “foo” / “bar”.

How can I do this in Laravel 11?

PHP Imagick – Scale Image – output not satisfying

I’m trying to scale a png image. The top most is scaled by the browser (so on client side):

<img src="data:image/png;base64,{articleImage.fileContent}" style="max-width: 200px; max-height: 200px;" />

The bottom one is scaled by PHP Imagick (so on server side):

$image->resizeImage($newWidth, $newHeight, Imagick::FILTER_BOX, 1);

The scaled output is not satisfying to me. I played a lot with Imagick:FILTER_ and blur factor (1) – but didn’t achieved a good result. Any hint from your side? Thank you!

enter image description here

WordPress SQL Query – Update

Very new to update queries.

My WordPress installation has a table which I need to update via a cron, need to change value via update (ideally) – I know wordpress has built in wpdb for this but I cannot for the life in me work it out.

All I want to do is change values in column ‘status’ if they contain ‘unconfirmed’ to ‘subscribed’

I have a working SQL query which I can confirm in phpmyadmin:

UPDATE wp_mailpoet_subscribers SET status = REPLACE(status, 'unconfirmed','subscribed');

So I my plan is to create a php file in wordpress and then setup a cron job, I have a bunch of others in the site (I didn’t make it!) which work fine.

The code I have tried is as follows:

global $wpdb;
$wpdb->query("UPDATE wp_mailpoet_subscribers SET status = REPLACE(status, 'unconfirmed','subscribed'");

Any help why this doesn’t work would be greatly appreciated

Thanks

global $wpdb;
$wpdb->query(“UPDATE wp_mailpoet_subscribers SET status = REPLACE(status, ‘unconfirmed’,’subscribed'”);

Laravel Inertia

I’m working on a project using Laravel with React and Inertia.js. After making changes to my components and routes, I’m unable to see them reflected in the browser. I’ve run the following commands to clear the caches:

php artisan view:clear

php artisan cache:clear

php artisan route:clear

php artisan config:clear

Despite these actions, the updates are still not showing. I’ve confirmed that I’m in development mode and there are no error messages in the console. I’ve also tried refreshing the page and clearing the browser cache. Is there something I might be overlooking or additional steps I should try to resolve this issue? Any guidance or suggestions would be greatly appreciated!

eratic php inquiry response

I have a web page that controls and inputs switch states into a database.
I confirm this works.
There is a php program to read the switch states from the database via a Get command and send this data in a json format to a remote microprocessor.
As I sit behind a Nat an ESP32 periodically calls in to Get those switch states and changes processor pin states accordingly for control.
From experience interrogating the Json data at microprocessor level and changing the pin status also works.

The Problem..
I can call the php directly via a web interface (Chrome, firefox) and get the pin state readings accurately in real time.
However when making the same inquiry via the Esp the intial readings upon start up are acurate but subsequent changes are erratic sometimes received but generally repeating the initial state. This has been confirmed by printed responses at microprpocessor level.
This will clear after varying times whereupon that readings at that time will become the default.
Switching off and rebooting the microprocessor makes no difference – strangely it defaults back to the last originating state.!

It is as though the states via an Esp call are cached somewhere and repeated as against a direct web inquiry through the php which does show the changes.

Is this a script problem ? and any ideas on how to correct it.

Code:

    <?php
    // board = 7
    // Database connection parameters
    $servername = "localhost";
    $dbname = "xxxxxxx";  // Database name
    $username = "yyyyyyy";  // User
    $password = "xxxx";  // Password

    $gpio = $state = $data = $row = "";

    // Create connection
    $conn = new mysqli($servername, $username, $password, $dbname);

    // Check connection
    if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
    }

    // Set the board number for the query
    $board_number = 7;

    // Prepare and execute the SELECT query
    $sql = "SELECT gpio, state FROM switch_outputs WHERE board = ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("i", $board_number);
    $stmt->execute();
    $result = $stmt->get_result();

    // Fetch data and encode it as JSON
    $data = array();
    while ($row = $result->fetch_assoc()) {
    $data[] = $row;
    }

    // Update the database with the current time of the last request
    $update_sql = "UPDATE switch_outputs SET last_request = NOW() WHERE board = ?";
    $update_stmt = $conn->prepare($update_sql);
    $update_stmt->bind_param("i", $board_number);
    $update_stmt->execute();

    // Set content type to JSON and output the data
    header('Content-Type: application/json');
    echo json_encode($data);

    // Close statements and connection
    $stmt->close();
    $update_stmt->close();
    $conn->close();
    ?>

The Hosting service (Blue Host) claim it is a scripting problem. Server caching has been cleared without changing the resposne. I am unable to to check the database loggings as it is a shared hosting acount.
My concern is consistency of a timely resposne. Sometimes it works – sometimes it just locks up.