Set CSRF/XSRF token with laravel + react

I’m trying to learn and build a backend using Laravel 12, it comes with inertia that allows me to manage my auth tokens and CSRF token for a React app, but based on my understanding it’s for the React app that is in tandem already with that laravel app.

I have my own separate React app in which I want to call the APIs from. So what I’m trying to do is call some auth APIs in Laravel backend specifically the '/register' but it requires me to have CSRF token.

So I tried to start session by hitting a get request on '/' , this will give me XSRF cookie in my frontend. I was able to get those cookie but then when I hit a request again on '/register', the XSRF token is present but in cookies and not in the actual header of the request and this will give me error of “message: CSRF token mismatch.”.

Response header for getting token looks like this:

access-control-expose-headers:
XSRF-TOKEN
cache-control:
no-cache, private
connection:
close
content-type:
text/html; charset=UTF-8
date:
Sun, 02 Mar 2025 07:59:55 GMT
host:
127.0.0.1:8000
link:
<http://127.0.0.1:8000/build/assets/app-wKvlsDeH.css>; rel="preload"; as="style", <http://127.0.0.1:8000/build/assets/app-0LmJ1Xg0.js>; rel="modulepreload", <http://127.0.0.1:8000/build/assets/welcome-CmFPhQLK.js>; rel="modulepreload"
set-cookie:
XSRF-TOKEN=eyJpdiI6InNHRFowZnVNSkoyUjZNN2R4Q3JpRHc9PSIsInZhbHVlIjoiQ0V2d0JsZDI4U0tGY0I0WkNnM0tzVnkwRWJNYmJNZWp5ZEx2bTZHRzUvZE81Y1JjZ0FzdXNFenM0citzUFJjcmV3bk1MZ2FaYjFqYTBBTFhzbWNabDMyalBkOFg1UTcxb1p3MlhWTllLWThHVE1DSVJRTVJ2WTRlTUhVazI5V2oiLCJtYWMiOiI4MzkyODVhMmNmYzAzMzYyYTNmNzRjZThjZDZiNjFlNTRhNDc3NDQ0OWZmZmVmOWNhMmQxNzg3MjAxOGM4NDM1IiwidGFnIjoiIn0%3D; expires=Sun, 02 Mar 2025 09:59:55 GMT; Max-Age=7200; path=/; secure; samesite=none
set-cookie:
laravel_session=eyJpdiI6IkluY1hPRFFNWE52V3JpbTFCRmVyZVE9PSIsInZhbHVlIjoiOHduT3BZWWFza3pvdCt6K2ZLOFBnSG1UVVN2dVJNTUZiRHhYeUFDNld1WWlvNWZOQjRGMU80MlIzZk1uTjVVb2hEdytWNEtMYkJjYmlvdmdPTjJYL3JhQWZTWmc4MXlJMWg5RVBjN1NFTXMwU2ZKZlBLZkEyZ2owUzJtVW5JMlkiLCJtYWMiOiI3N2Y0MzYzMTQxNTU5MzdmODY3MDY5N2U1NGRjODA4MGUzOTQ4N2Y0MTAwMWNmY2E1MTI5MDIwYzIxNTIwMzQwIiwidGFnIjoiIn0%3D; expires=Sun, 02 Mar 2025 09:59:55 GMT; Max-Age=7200; path=/; secure; httponly; samesite=none

Request header for /register looks like this:

cookie:
XSRF-TOKEN=eyJpdiI6IlM3SW5FMU5LOXV1emp1ckhvcWpFb1E9PSIsInZhbHVlIjoiWXhaaHFDQlRWdG5YclVHY2dJeUppY0ZtNlNENHdGblExbWc5VnJhNGQ1QW1FejVBMzZUOVJCSXNibFJ2Slc5QzNrMGo5RW9WVWpXOU55NmNta2N1cjl4dWxBcTlPT2tib3R1blhIV1hvdVdIaVBaM215ejRockNKTmc5b0RnSnQiLCJtYWMiOiJhMzBiNWRhYTliZWU4M2QyYTY2YTgxYzU3NTE3MTNhMzA5Y2U1ZmJkZWU0Mzg4MjQ2NGY0MjgzOTlkM2ZkNGY4IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6Ikpwd0hwZnh1ZmM4d29mUHhKdXNnNUE9PSIsInZhbHVlIjoiNW5EWHpUMElQQWRPc3RLVGRUVndkUnRNZFBrWUtDYTV0eUU4RXYvUFhpRzU2VmN5dGtIaitxUU41dGZ6ODYyWDVRMDlDbGpTSFhGYi95Vmk5UDU4QklXK05jUFBVZTVaSkRWVlRFMFByVUE5Vmt5S0Q3UmwzZzE5ZHpRYk9jU2MiLCJtYWMiOiI0YmZiNWI1ZjY5ZjExZmIxN2FjYjhhZWQwNzc5NjQwNjc2OTBmNDVjOWYxZjU5YWZmZjE3NTcwNDBkZGM0MDc4IiwidGFnIjoiIn0%3D
host:
127.0.0.1:8000
origin:
http://localhost:3000

I think this should have XSRF-TOKEN variable also in header to be successful. What am I doing wrong in here?

const axiosInstance: AxiosInstance = axios.create({
  baseURL: 'http://127.0.0.1:8000',
  withXSRFToken: true,
  withCredentials: true,
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json",
  },
})

Carbon diffInSeconds() returning negative value

I recently updated nesbot/Carbon from 2.67 to 3.8.6. When running the following piece of code, I used to get a positive value, now I get a negative value. Has the order of operation changed for diffInSeconds()?

$time_before = Carbon::now();
// << call that takes 85 s >>
$time_after = Carbon::now();
$duration_in_secs = $time_after->diffInSeconds($time_before);

This gives me:

Duration: -84.766262 seconds
before:2025-03-02 02:53:35
after:2025-03-02 02:55:00

brew install [email protected] gives CONNECT_CR_SRVR_HELLO:sslv3 alert handshake failure

I am trying to install PHP8.3 using brew install [email protected] . But I’m getting the following

==> Downloading https://libzip.org/download/libzip-1.11.3.tar.xz
curl: (35) error:14004410:SSL routines:CONNECT_CR_SRVR_HELLO:sslv3 alert handshake failure                                                                                                                                                          

Error: [email protected]: Failed to download resource "libzip"
Download failed: https://libzip.org/download/libzip-1.11.3.tar.xz

PHP – FPDI class not found in production environment

I am using FPDI on a PHP CMS to generate PDFs via a scheduler command. Everything works fine on my development environment (Debian 11), but when running the same code on production (Debian too), I get the following error:

Class ‘setasignFpdiFpdi’ not found | Error thrown in file /FPDF/src/Fpdi/MultiCell.php in line 5

structure Folder of FPDF (see attached screenshot)

structure folder

Here is my custom MultiCell.php class:

<?php

namespace setasignFpdiMultiCell;

class MultiCell extends setasignFpdiFpdi
{
...
}

Fpdi.php :

<?php

namespace setasignFpdi;

use setasignFpdiPdfParserCrossReferenceCrossReferenceException;
use setasignFpdiPdfParserPdfParserException;
use setasignFpdiPdfParserTypePdfIndirectObject;
use setasignFpdiPdfParserTypePdfNull;

class Fpdi extends FpdfTpl
{
    use FpdiTrait;
    use FpdfTrait;

    /**
     * FPDI version
     *
     * @string
     */
    const VERSION = '2.6.1';
}

autoload.php :

<?php

/**
 * This file is part of FPDI
 *
 * @package   setasignFpdi
 * @copyright Copyright (c) 2024 Setasign GmbH & Co. KG (https://www.setasign.com)
 * @license   http://opensource.org/licenses/mit-license The MIT License
 */

spl_autoload_register(static function ($class) {
    if (strpos($class, 'setasignFpdi\') === 0) {
        $filename = str_replace('\', DIRECTORY_SEPARATOR, substr($class, 14)) . '.php';
        $fullpath = __DIR__ . DIRECTORY_SEPARATOR . $filename;

        if (is_file($fullpath)) {
            /** @noinspection PhpIncludeInspection */
            require_once $fullpath;
        }
    }
});

How I load FPDI in my export command :

public function exportCommand() {
    require_once(ExtensionManagementUtility::extPath('myProject').'Resources/Private/FPDF/fpdf.php');
    require_once(ExtensionManagementUtility::extPath('myProject').'Resources/Private/FPDF/src/autoload.php');
    require_once(ExtensionManagementUtility::extPath('myProject').'Resources/Private/FPDF/src/Fpdi/MultiCell.php');

    ini_set('max_execution_time', 0);
    ini_set('memory_limit','-1');

    ...
}

what I’ve tried :

I renamed the directory from FPDF to Fpdi to match the namespace exactly. It did not fix the issue.

I checked case sensitivity on Linux. All folder and file names match their respective namespaces.

I tried to change my Multicell.php like this :

namespace setasignFpdiMultiCell;

use setasignFpdiFpdi;

class MultiCell extends Fpdi
{...}

Any help would be greatly appreciated!

PS : My project don’t use composer

Using a stdClass instead of a mock

I have had a few situations where…

  • I cannot use a normal mock because the object being mocked is hard coded (ie uses new SomeName() instead of using dependency injection ways). [and…]
  • I cannot use Mockery’s alias: or overload: mocks because the class has already been loaded. [and…]
  • I cannot use Laravel’s facade mocks because the class is not a facade.

So as a last resort, I have created a class within the same file as the test, called Mock_Class_Name and used PHP’s alias() function to replace the real class that I want to mock with my class.

A problem with this is – unless it is a Laravel alias – I can’t simulate any sort of partial mocking so my class has to define ALL functions which get called and not just the ones I want to mock. (If it’s a Laravel alias which is being mocked, then I can just extend the real class but that does not work normally.)

Pseudo example:

class someTest extends TestCase {

     publicfunction firstTest(){
          class_alias(Support_Class_Mock::class, 'SupportClass');

          //// rest of test code here

     }
}

class Support_Class_Mock extends AppSupportClass

{
    public static function oauthGetAccessToken($beep,$boop){
        return 'OAuth Successful';
    }
}

My question:
Is what I am doing an acceptable “last resort” practice? (Or is there a better way?)

WordPress custom email subscription form based on user settings [closed]

I have a wordpress website where visitors may be struggling with their grasp on reality and their mental health. other visitors are interested in spirituality and there may be an overlap of the two.

I do not want to shows ads on the website for users who are struggling with their mental health or having less than positive experiences with spirituality as this could cause complications and we just want to direct them to professional help and we do not want to lose contact with them.

  1. I need to setup a user setting “Are you experiencing any negative effects from your spiritual journey, or do you have any mental health concerns, even minor ones?” the choices would be yes, no, not sure. This will be used to display ads if the user selects no, then the website will keep a record of this via a cookie. It also has further functionality.

  2. I need to setup a email subscription form, primarily focused on keeping connected the individuals so that we may send them an email once a week. reminding them that they may be struggling with mental health etc… Support links to professionals and what not.
    further to this I would like two checkboxes “Support” and “inspiration, exclusive content, and special offers”

Further to my earlier point, I do not want to send any confusing emails to someone who may be struggling with their grasp on reality and/or suffering from mental health complications. therefore I would have the “inspiration, exclusive content, and special offers” option grayed out if they choose Yes or Not sure.

  1. Backend, I should be ok with this as there are many options available to me. I will most likely be writing something custom on my linux/ plesk server

I am fairly certain that I am not going to find anything like this out of the box and I am not interested in paying very much for someting.

I know that you would like to see what I have so far, unfortunately that is nothing.

I am a programmer but this will be the first time that I have written any javascript and or php.

Therefore, I hope that you can put this technicality aside.

If anyone can point me in the right direction I would be grateful.

In the mean time, I am going to try and figure this out.
I will update back if I manage to put anything together.

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ‘AREA-6557-43’ for key ‘areas_name_program_id_unique’ [closed]

class Area extends Model 
{
   

    protected static function rules(): array
    {
        return [
            'program_id' => 'required|integer|exists:programs,id',
            'name' => [
                'required',
                'string',
                'max:191',
                Rule::unique('areas', 'name')
                    ->where('program_id', request()->input('program_id'))
                    ->ignore(request()->route('record')),
            ],
            'status' => 'required|boolean',
        ];
    }
}

request()->input('program_id') is not bringing me the program id of the filament 3.2 form to create a new area in AreaResources

request()->input('program_id') should bring an integer id for example 43

Fetch products using slug in Magento

<?php 
    $adminToken = ""; 
    $slug = "dish-washing-powder"; 
    $url = "example.com/rest/V1/…"; 
    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer $adminToken", "Content-Type:application/json" ]); 
    $response = curl_exec($ch); 
    curl_close($ch);
    $products = json_decode($response, true); echo "<pre>"; 
    print_r($products); echo "</pre>"; 
?>

Not fetching the product details.

Output look like this. I need to use slug instead of sku.

Below is the json I’m getting while running on Postman.

Any help would be appreciated. Thanks in advance

{
  "items": [],
  "search_criteria": {
    "filter_groups": [
      {
        "filters": [
          {
            "field": "url_key",
            "value": "dish-washing-powder/",
            "condition_type": "eq"
          }
        ]
      }
    ]
  },
  "total_count": 0
}

Any help would be appreciated.

My expected output is like the below

{
    "id": 391,
    "sku": "abc-1",
    "name": "dish washing powder",
    "attribute_set_id": 4,
    "price": 12.68,
    "status": 2,
    "visibility": 4,
    "type_id": "simple",
    "created_at": "2020-10-27 11:30:00",
    "updated_at": "2024-12-03 04:19:58",
    "weight": 0.7,
    "extension_attributes": {
        "website_ids": [
            1
        ],
        

Note: I was able to get it as a sku by fetching like this.
https://example.com/rest/V1/products/{sku}

For slug this seems to work – https://example.com/rest/V1/products?searchCriteria[filterGroups][0][filters][0][field]=url_key&searchCriteria[filterGroups][0][filters][0][value]=my-product-name&searchCriteria[filterGroups][0][filters][0][condition_type]=eq

But can I simplify it more like the sku url.

Scrutinizer code checking is failed because of composer constraint rejection [duplicate]

I developed my Laravel package https://github.com/itstructure/laravel-rbac and ran a code checking in a https://scrutinizer-ci.com/g/itstructure/laravel-rbac/inspections/a2b33b54-5498-43fa-8a59-0adf00e71f88.

As a result i had this error (The requested package exists but these are rejected by your constraint):

You are using Composer 1 which is deprecated. You should upgrade to Composer 2, see https://blog.packagist.com/deprecating-composer-1-support/
Loading composer repositories with package information
Warning from https://repo.packagist.org: Support for Composer 1 will be shutdown on August 1st 2025. You should upgrade to Composer 2. See https://blog.packagist.com/shutting-down-packagist-org-support-for-composer-1-x/
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
– The requested package itstructure/laravel-grid-view ^1.1.6 exists as itstructure/laravel-grid-view[1.0.0, 1.0.1, 1.0.10, 1.0.11, 1.0.12, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.0.9, 1.1.0, 1.1.1, 1.1.2, 1.1.3, 1.1.4, 1.1.5, dev-dev, dev-master] but these are rejected by your constraint.

The tag 1.1.6 exists in my package, but error report says that does not. Also it is not clear for me why it says “You are using Composer 1 which is deprecated. You should upgrade to Composer 2”.

Scrutinizer compile config: https://github.com/itstructure/laravel-rbac/blob/master/.scrutinizer.yml

I had never such error. Can you help?

Yajra not making ajax call and not rendering any data

I am trying to implement Yajra datatables in my new Laravel 12 project but it is not rendering any data and I also don’t see any ajax call in network.

Here are my configurations.

composer.json "yajra/laravel-datatables": "^12"

package.json

"devDependencies": {
    "laravel-datatables-vite": "^0.6.1",
     ...
}

app.scss

// Fonts
@import url('https://fonts.bunny.net/css?family=Nunito');
// Variables
@import 'variables';

// Bootstrap
@import 'bootstrap/scss/bootstrap';

// DataTables
@import 'bootstrap-icons/font/bootstrap-icons.css';
@import "datatables.net-bs5/css/dataTables.bootstrap5.min.css";
@import "datatables.net-buttons-bs5/css/buttons.bootstrap5.min.css";
@import 'datatables.net-select-bs5/css/select.bootstrap5.css';

app.js import 'laravel-datatables-vite';

controller

public function index(UsersDataTable $dataTable)
{
    return $dataTable->render('users.index');
} 

UsersDatatable.php

public function dataTable(QueryBuilder $query): EloquentDataTable
{
    return (new EloquentDataTable($query))
        ->setRowId('id');
}

public function query(User $model): QueryBuilder
{
    return $model->newQuery()->with('roles');
}

public function html(): HtmlBuilder
{
    return $this->builder()
        ->setTableId('users-table')
        ->columns($this->getColumns())
        ->minifiedAjax()
        ->orderBy(1)
        ->selectStyleSingle()
        ->buttons([
            Button::make('excel'),
            Button::make('csv'),
            Button::make('pdf'),
            Button::make('print'),
            Button::make('reset'),
            Button::make('reload')
        ]);
}

public function getColumns(): array
{
    return [
        Column::make('id')->title('ID'),
        Column::make('name')->title('Name'),
        Column::make('email')->title('Email'),
        Column::computed('roles')->title('Roles'),
        Column::make('created_at')->title('Created At'),
        Column::make('updated_at')->title('Updated At'),
    ];
}

index.blade.php

<x-layouts.app>
    <div class="container">
        <h2>User Management</h2>
        {{ $dataTable->table() }}
    </div>
</x-layouts.app>

@push('scripts')
    {{ $dataTable->scripts() }}
@endpush

Issue

The table is rendered with column names, but no data is displayed, and there are no AJAX calls in the network tab. Here’s what the table looks like:

Datatable View

What I’ve Tried

  • Verified that the @stack(‘scripts’) directive is present in my layout.

  • Checked for JavaScript errors in the console (none found).

  • Cleared Laravel cache using php artisan cache:clear, php artisan view:clear, etc.

Anilist graphql query

can anyone help me?

how to mutate graphql query to add manga to anilist manga favorite by current login user?

this is how i done it
favorite.php

<?php
session_start();
header("Content-Type: application/json");

// Check if access token is available
if (!isset($_SESSION['access_token'])) {
    echo json_encode(["error" => "Access token not found. Please log in first."]);
    exit;
}

// Get Manga ID from AJAX request
$data = json_decode(file_get_contents("php://input"), true);
if (!isset($data['mangaId'])) {
    echo json_encode(["error" => "No manga ID provided."]);
    exit;
}

$mangaId = (int) $data['mangaId'];

// AniList API URL
$url = "https://graphql.anilist.co";

// GraphQL Mutation Query
$query = <<<GQL
mutation ($mangaId: Int) {
  ToggleFavourite(mangaId: $mangaId) {
    manga {
      edges {
        node {
          id
          title {
            romaji
            english
          }
        }
      }
    }
  }
}
GQL;

// Prepare request payload
$variables = ["mangaId" => $mangaId];
$payload = json_encode(["query" => $query, "variables" => $variables]);

// Set headers
$headers = [
    "Content-Type: application/json",
    "Authorization: Bearer " . $_SESSION['access_token']
];

// Initialize cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

// Execute request and get response
$response = curl_exec($ch);
curl_close($ch);

file_put_contents("debug_log.txt", $response . PHP_EOL, FILE_APPEND);
echo $response;
?>

button

<div id="favoriteButton" class="bookmark dropright favourite">
                                    <button class="btn btn-lg btn-secondary1 h-100" data-manga-id="<?php echo htmlspecialchars($manga['id']); ?>">
                                    <span>Favorites</span>
                                    <i class="fa-thin fa-heart"></i>
                                    </button>
                                 </div>

script

<script>
        document.getElementById("favoriteButton").addEventListener("click", function () {
            let mangaId = this.getAttribute("data-manga-id");

            fetch("favorite.php", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({ mangaId: mangaId })
            })
            .then(response => response.json())
            .then(data => {
                if (data.errors) {
                    alert("Error: " + data.errors[0].message);
                } else {
                    alert("Manga successfully added to favorites!");
                }
            })
            .catch(error => console.error("Error:", error));
        });
    </script>

the reponse return success but when i go to my anilist account, the manga is not there in favourites

the reponse return success but when i go to my anilist account, the manga is not there in favourites

Composer is not install in Windows 11 and PHP 8.2.12 [duplicate]

I have new Laptop which has windows 11 installed. I have also install XAMPP which has php 8.2.12 version. Now i want to install composer in my system but it is not allowing me to install. It gives me error like

The Composer installer script was not successful [exit code 1].

OpenSSL failed with a 'certificate verify failed' error. This indicates a problem with 
the Certificate Authority file(s) on your system, which may be out of date.

Certificate location [from openssl.cafile ini setting]: 
C:xamppphpcacert.pem

The php.ini used by your command-line PHP is: C:xamppphpphp.ini

Script Output:
The "https://getcomposer.org/versions" file could not be downloaded: SSL operation 
failed with code 1. OpenSSL Error messages:
error:0A000086:SSL routines::certificate verify failed
Failed to enable crypto
Failed to open stream: operation failed

I have change certificate file as suggest from CHAT GPT. as given below

curl.cainfo = "C:xamppphpcacert.pem"
openssl.cafile = "C:xamppphpcacert.pem"

I have also set environment variable PATH to C:XAMPPPHPPHP.exe and also check in CMD that it shows me PHP version 8.2.12 which is currently installed. I have also try to install composer manually using commands like

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"

But it gives me error like below

Downloading...
The "https://getcomposer.org/versions" file could not be downloaded: SSL operation failed 
with code 1. OpenSSL Error messages:
error:0A000086:SSL routines::certificate verify failed
Failed to enable crypto
Failed to open stream: operation failed
Retrying...
The "https://getcomposer.org/versions" file could not be downloaded: SSL operation failed 
with code 1. OpenSSL Error messages:
error:0A000086:SSL routines::certificate verify failed
Failed to enable crypto
Failed to open stream: operation failed
Retrying...
The "https://getcomposer.org/versions" file could not be downloaded: SSL operation failed 
with code 1. OpenSSL Error messages:
error:0A000086:SSL routines::certificate verify failed
Failed to enable crypto
Failed to open stream: operation failed
The download failed repeatedly, aborting.

Can anyone suggest me what to do with this issue?

What WooCommerce hooks should I use to display a short product description on a page powered by Ellementor?

I am using the OceanWP theme and Elementor Pro. I am using Elementor widgets: PRODUCTS and OceanWP widgets: WOO – PRODUCTS. These widgets do not allow you to display a SHORT PRODUCT DESCRIPTION from WooCommerce under the PRODUCT TITLE.

I have created two shortcodes in PHP that allow this. The description appears either at the very top of the product field or at the very bottom. Changing priorities does nothing. I cannot place the SHORT PRODUCT DESCRIPTION exactly between the PRODUCT NAME and its PRICE. Please help.

  1. PHP CODE for the Elementor widget – PRODUCTS:
    // SHOWING A SHORT DESCRIPTION UNDER THE PRODUCT TITLE IN THE PRODUCTS WIDGET by Elementor

    add_action( 'elementor/widget/render_content', function( $content, $widget ) {
        // Check if it's a Products widget in Elementor
        if ( 'woocommerce-products' === $widget->get_name() ) {
            // Get the current HTML content of the widget
            ob_start();
            add_action( 'woocommerce_after_shop_loop_item', function() {
                global $product;
                $short_description = $product->get_short_description();

                if ( $short_description ) {
                    echo '<div class="elementor-product-short-description" style="margin-top: 5px; font-size: 14px; color: #666;">';
                    echo wp_kses_post( $short_description );
                    echo '</div>';
                }
            }, 15 );
            ob_end_flush();
        }
        return $content;
    }, 10, 2 );
  1. PHP CODE for the OceanWP widget – WOO – PRODUCTS:
    // DISPLAYING A SHORT DESCRIPTION UNDER THE PRODUCT TITLE IN THE WIDGET WOO - PRODUCTS by OceanWP

    add_action( 'woocommerce_after_shop_loop_item_title', function() {
        global $product;
    
        if ( ! $product ) {
            return;
        }

        // Download a short description of the product
        $short_description = $product->get_short_description();

        // If the description exists, we add it ONLY under the title
        if ( $short_description ) {
            echo '<div class="elementor-product-short-description" style="margin-top: 5px; font-size: 14px; color: #666;">';
            echo wp_kses_post( $short_description );
            echo '</div>';
        }
    }, 15 ); // We changed the priority to 15 so that it is AFTER the title but before the price and button

Best regards,
Krzysztof