datatables.net alerts Invalid Json Response. I can’t find anything wrong with the json [closed]

I am using Datatables.net to display results of an oracle query. Query works fine and I appear to be getting the right JSON output, but DataTables complains that my JSON is invalid. I have this javascript:

ajax: {
  url: "php/requests.php",
  type: "POST",
  dataSrc: ""
},
paging: false,
scrollY: '60vh',
scrollCollapse: true,
// note:  DataTables.render.number(thousandsSeparater,decimalSeparator,precision,[prefix ie '$'],[suffix])
columns: [
    { data: "Request_Id" },
    { data: "Description" },
    { data: "Requestor" },
    { data: "Request_Date" },
    { data: "Processed", className: "dt-right", render: DataTable.render.number(',', '.', 0) },
    { data: "Processed_Rate", className: "dt-right", render: DataTable.render.number(',', '.', 1) },
    { data: "Pending", className: "dt-right", render: DataTable.render.number(',', '.', 0) },
    { data: "Succeeded", className: "dt-right", render: DataTable.render.number(',', '.', 0) },
    { data: "Success_Rate", className: "dt-right", render: DataTable.render.number(',', '.', 1) }
    { data: "Failed", className: "dt-right", render: DataTable.render.number(',', '.', 0) },
],
order: [0, 'asc']

requests.php gets called as expected when the page loads and this json string is output:

[
    {
        "Request_Id": "10082",
        "Description": "test",
        "Requestor": "[email protected]",
        "Request_Date": "27-AUG-25",
        "Processed": 354,
        "Processed_Rate": 69.00584795321637,
        "Pending": 159,
        "Succeeded": 354,
        "Success_Rate": 100,
        "Failed": 0
    }
]

(as copied from Edge/developer tools/network/response )

this is the message that pops up:
enter image description here
What am I missing?

How to override PHP syntax coloring in VSCode Language

I tried both including source.php after my match rule and injection into the PHP language syntax.

Including the source shows PHP syntax coloring without my override, whereas injection shows my override without PHP coloring.

Attempt PHP Syntax My Syntax Override
With Injection
Include PHP Source (source.php)

I would like to see both work at the same time where my syntax overrides the PHP syntax.

Any ideas what is happening or how to achieve this please?

My code setup:

# Language
"languages": [
    {
        "id": "phpf",
        "aliases": ["PHPF", "phpf"],
        "extensions": [".phpf"],
        "configuration": "./language-configuration.json",
        "icon": {
        "light": "file-icons/phpf.png",
        "dark": "file-icons/phpf.png"
        }
    }
]

# Grammar
"grammars": [
    {
        "language": "phpf",
        "scopeName": "source.phpf",
        "path": "./syntaxes/phpf.json",
        "injectTo": ["source.php"]
    }
]

# Syntax
{
    "scopeName": "source.phpf",
    "fileTypes": ["phpf"],
    "name": "PHPF",
    "injectionSelector": "L:source.php",
    "patterns": [
    {
        "name": "phpf.a",
        "match": "___[A-Z]+___"
    },
    {
        "include": "source.php"
    }
    ]
}

# Coloring
"configurationDefaults": {
    "editor.tokenColorCustomizations": {
        "textMateRules": [
        {
            "scope": "phpf.a",
            "settings": {
            "fontStyle": "bold",
            "foreground": "#e24d33"
            }
        }
        ]
    }
}

XML with attributes to array in PHP

I am trying to convert an XML string into multi-dimensioned PHP array. The difficulties are that XML comes with attributes and has nested values. My code works at parent level data but I am not sure how to deal with sub-levels recursively.

A sample XML is as follows:

<root>
    <item id="1" name="ItemOne">Item Value 1</item>
    <item id="2" name="ItemTwo">
        <subb>Sub Value 1</subb>
        <subb>Sub Value 2</subb>
    </item>
    <item id="3" name="ItemThree">Value 3</item>
    <something>something value</something>
</root>

This is my current function to achieve this:

$xmlString = '<root><item id="1" name="ItemOne">Item Value 1</item><item id="2" name="ItemTwo"><subb>Sub Value 1</subb><subb>Sub Value 2</subb></item><item id="3" name="ItemThree">Value 3</item><something>something value</something></root>';

function xmlToArray($xmlObject) {
    $array = [];
    foreach ($xmlObject as $item) {
        // Convert attributes to an array
        $attributes = (array)$item->attributes();
        // Add the text value to the attributes array if it exists
        $attributes['@value'] = trim((string)$item);
        $key = (string)$item->getName();
        if (isset($make_sub_array) && in_array($key, $make_sub_array)) {
            $array[$key][] = $attributes;
        }
        elseif (isset($array[$key])) {
            $make_sub_array[] = $key;
            $tmp = $array[$key];
            unset($array[$key]);
            $array[$key][] = $tmp; //existing data
            $array[$key][] = $attributes; //this data
        }
        else $array[$key] = $attributes;
    }
    return $array;
}
// Load the XML string into a SimpleXMLElement object
$xmlObject = simplexml_load_string($xmlString);
$array = xmlToArray($xmlObject);
exit('<pre>'.print_r($array,1).'</pre>');

The resulting array structure is below, and I require your help about how I can process the array under second item. I would like it to be processed the same way as the parent one: if the item name is repeated then it will be included as [] so I get number as its parent, otherwise [itemname].
Thank you

Array
(
    [item] => Array
        (
            [0] => Array
                (
                    [@attributes] => Array
                        (
                            [id] => 1
                            [name] => ItemOne
                        )
                    [@value] => Item Value 1
                )
            [1] => Array
                (
                    [@attributes] => Array
                        (
                            [id] => 2
                            [name] => ItemTwo
                        )
                    [@value] => 
                )
            [2] => Array
                (
                    [@attributes] => Array
                        (
                            [id] => 3
                            [name] => ItemThree
                        )

                    [@value] => Value 3
                )
        )
    [something] => Array
        (
            [@value] => something value
        )
)

PHP XAMPP Curl Request Slow on Windows 10 for JSON payloads [closed]

I’m sending JSON data to an external API using PHP cURL on Windows 10 with XAMPP (PHP 8.3).

  • Small JSON payloads (1–2 KB) return a response normally within ~2 seconds.
  • As soon as the payload gets a few extra characters or items, the request takes a very long time and sometimes errors out.
  • The same request works instantly in Postman.

Here is a simplified version of my code:

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://api.example.com/validate',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($data),
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer ...'
    ],
]);

$response = curl_exec($curl);

curl_close($curl);

Things I’ve tried:

  • Increasing post_max_size, memory_limit, max_execution_time in php.ini.
  • Disabling JSON_PRETTY_PRINT.
  • Testing with JSON payloads of different sizes.
  • Running the script via CLI (faster than through browser).

Environment:

  • Windows 10
  • XAMPP (Apache + PHP 8.3)
  • cURL enabled
  • JSON payloads range from 1 KB to 100+ KB

Symptoms:

PHP cURL is much slower than Postman for slightly larger payloads.

With few more JSON values request may fail or hang even with less few items request complete in under 2 seconds

Questions:

  1. Why does PHP cURL become slow or fail with slightly larger JSON payloads in this environment?
  2. How can I reliably send larger JSON payloads via cURL on XAMPP without long delays or errors?
  3. Are there any Windows/XAMPP/PHP specific settings I need to adjust (DNS, SSL, buffer sizes, timeouts, etc.)?

Migrations & Seeders & Command for production data [duplicate]

Recently after some research I came up with a question: how to handle default / initial data population in a Laravel project which goes live: should it go into seeders or migrations? I’ve seen two very different schools of thought.

  • Nuno Maduro says:

    Seeders should only be used for environment-specific data (local or test), and not for default system values. Database seeders become outdated over time and may no longer reflect the true state of your production data. This can introduce inconsistencies if you need to re-run migrations to deploy your app elsewhere. In contrast, migrations are inherently reliable because they define the exact structure and transformations that shaped your production data, guaranteeing consistency across environments.

    YouTube video in which Nuno talks about seeders

  • Another developer explained why they always use migrations for default values:

    • They support dependencies between tables.

    • Easier to revert a release by using down() to remove the inserted data.

    • Avoids the risk of someone forgetting to run the seeders, or accidentally running test seeders in production.

  • On the other hand, many developers say:

    Migrations should migrate schema, not seed data.

    But they often don’t address the fact that default values are actually part of the schema of the application.

In my project I have two different types of default data:

  1. Roles (user, admin): These is a critical system data, so I’m leaning toward adding them in a migration.

  2. DishCategories & DishSubcategories: Here it gets tricky. I have a large predefined array of categories and subcategories (kind of like a starter set). To avoid bloating the migration file, I moved that array into a separate PHP file and include it when inserting the data.

Is this an acceptable approach?

On the one hand, these are not “test” values, they are part of the actual application logic (used in search). On the other hand, they can evolve later by being managed in the admin panel.

Laravel Daily also mentioned a possible issue when putting data population inside migrations:

  • During automated tests, when migrations are re-run, the default data might get inserted multiple times unless you use insertOrIgnore or similar safeguards.

  • This could lead to duplicate rows in test environments.

YouTube video in which Laravel Daily talks about those 2 approaches

Also there is 3 way of seeding data using custom artisan command, but I didn’t make such feature as it is similar to seeders and I’ll need to run this command right after running migrations

A code example of these 2 approaches (Seeder / Migration)

Seeder

class RolesSeeder extends Seeder
{
    public function run(): void
    {
        Role::create(['name' => 'user']);
        Role::create(['name' => 'admin']);
    }
}

Migration

    public function up(): void
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->id();
            $table->string('name')->unique();
            $table->timestamps();
        });

        $roles = [
            'user',
            'admin'
        ];

        foreach ($roles as $role){
            DB::table('roles')->insert([
                'name' => $role,
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        }
    }

There is already Laravel : Migrations & Seeding for production data on this topic, but because the question was asked a long time ago, I decided to raise this topic again

Shopware 6 – missing Paypal configuration admin panel page [closed]

I’ve installed Shopware 6.7.2 (latest) in Docker. After install and enable plugin Paypal and Stripe, there is no configuration admin panel. I see new payment methods from Stripe and Paypal in channel config, but no way access to configuration page plugin.

In Settings -> Extensions is listed here Paypal and stripe as active, but after click on … should be settings options but – Missing.

In my plugins lists, after click … should be available also settings link, but is only available option “unistall”

I know this is Paypal settings page, …/admin#/swag/paypal/settings/index/general when I try hardcoded access from browser on this page then i see blank page – no logs, no errors in console. I try rebuild administrator panel, cache remove, warmup etc, composer update. I spent 11 hrs today – still not work on docker.

Where to call manual authorisation in Laravel 12?

I am starting a new project, which is updating an old website, there is a requirement to move the old user accounts and user data over to the new system, when a user logs into the new site for the first time.

Therefore while I want to use the default Authentication in a Laravel 12 Starter Kit, it needs to be a manual authentication so that if the default system fails to find a match, I can look the user up on the old database in realtime, and start a worker to move the users data over and create a new account. That is all fine, but I am struggling to understand how to call the new authenticate function.

I have followed the authentication page (Laravel Docs) for manually authenticating users, thats fine, but I am struggling to understand how to correctly call it from the rest of the starter package.

Within AppHttpControllersAuthAuthenticatedSessionController.php there is this function

    public function store(LoginRequest $request): RedirectResponse
    {
        $request->authenticate();

        $request->session()->regenerate();

        return redirect()->intended(route('dashboard', absolute: false));
    }

Which is called when the Log In button on the login screen is clicked, but I think I need to replace the $request->authenticate(); line with the pointer to my bespoke function to attempt to authenticate the user.

However, if do something like

    #$request->authenticate();
    $bespokeAuth = new LogInController();
    $request = $bespokeAuth->authenticate($request);

while my code is executed, the results are not being returned back to the store function, hence error messages are not returned, and the system no longer moves to the next page on a successful login.

Can anyone tell me what I am missing, or doing wrong please?

How to remove public from the URL in Laravel 11 (shared hosting, no shell access) [closed]

/home/username/
    ├── laravel_project/
    │   ├── app/
    │   ├── bootstrap/
    │   ├── config/
    │   ├── database/
    │   ├── public/              
    │   │   ├── index.php
    │   │   ├── css/             
    │   │   ├── js/              
    │   │   └── images/          
    │   ├── routes/
    │   ├── storage/
    │   ├── vendor/
    │   └── artisan

how can i remove the public from the url in such a way that the asset should also load without the public

Ethers.js can call fetchMarketItems() fine, but PHP (web3p/web3.php) fails to decode the tuple[] return — how do I read struct[] results?

I have an NFT marketplace contract running on a local Hardhat node. The function below returns an array of structs:

struct MarketItem {
    uint256 tokenId;
    address payable seller;
    address payable owner;
    uint256 price;
    bool sold;
}
function fetchMarketItems() public view returns (MarketItem[] memory) {
    // ...
}

ABI excerpt:


{
  "inputs": [],
  "name": "fetchMarketItems",
  "outputs": [
    {
      "components": [
        { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
        { "internalType": "address payable", "name": "seller", "type": "address" },
        { "internalType": "address payable", "name": "owner",  "type": "address" },
        { "internalType": "uint256", "name": "price",  "type": "uint256" },
        { "internalType": "bool",    "name": "sold",   "type": "bool" }
      ],
      "internalType": "struct NFTMarketplace.MarketItem[]",
      "name": "",
      "type": "tuple[]"
    }
  ],
  "stateMutability": "view",
  "type": "function"
}

What works (JS / ethers.js)

if (!NFTMarketplaceABI) await loadABI();
const provider = new ethers.providers.JsonRpcProvider(); // Hardhat default localhost
const contract  = new ethers.Contract(
  "0x5FbDB2315678afecb367f032d93F642f64180aa3",
  NFTMarketplaceABI,
  provider
);
const data = await contract.fetchMarketItems();
console.log(data); // OK: array of items

What fails (PHP / web3p/web3.php)

Environment: PHP 8.x, Laravel, web3p/web3.php (Contract/HttpProvider/HttpRequestManager), Hardhat node accessible at http://172.17.0.1:8545 from inside Docker.

$provider        = new HttpProvider(new HttpRequestManager('http://172.17.0.1:8545'));
$contractAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3';

$abiPath = app()->basePath('public/NFTMarketplace.json');
$abiJson = json_decode(file_get_contents($abiPath), true);
if (!isset($abiJson['abi'])) {
    throw new Exception('ABI not found');
}

$contract = new Contract($provider, $abiJson['abi']);
$contract->at($contractAddress);

// sanity check
$contract->eth->getCode($contractAddress, 'latest', function ($e, $code) {
    if ($e !== null) throw new Exception($e->getMessage());
    if ($code === '0x' || $code === '0x0') throw new Exception('Address is not a contract');
});

$items  = [];
$errMsg = null;

$contract->call('fetchMarketItems', [], function ($err, $result) use (&$items, &$errMsg) {
    if ($err !== null) { $errMsg = $err->getMessage(); return; }
    $items = $result ?? [];
});

if ($errMsg) {
    throw new RuntimeException("fetchMarketItems failed: {$errMsg}");
}

Actual result: the callback receives an error and $errMsg is set. Example message I see:
fetchMarketItems failed: unsupported or invalid solidity type “tuple[]” (message may vary; earlier I’ve also hit decode-related errors while stepping through the library’s ABI decoder).

Expected: an array of market items, same as in ethers.js.

What I’ve tried

Verified the contract address and eth_getCode (non-zero).

Confirmed the ABI file is the same one ethers.js uses.

Tried both 127.0.0.1:8545 and 172.17.0.1:8545 (Docker host).

Searched issues/docs for tuple[]/struct[] return support in web3p/web3.php.

Tested simpler functions (e.g., returns uint256) — those work.

Question

Does web3p/web3.php support decoding returns of dynamic arrays of structs (tuple[]) from Solidity? If yes, what is the correct way to call/define the ABI so that Contract->call(‘fetchMarketItems’) returns decoded data? If not, what are practical workarounds in PHP (e.g., returning parallel arrays, using another ABI decoder/package, or different PHP Web3 library) to read struct[] results?

Notes

Node: Hardhat local chain

Contract: 0x5FbDB2315678afecb367f032d93F642f64180aa3

Framework: Laravel

Library: web3p/web3.php

Everything up to $contract->call(‘fetchMarketItems’, …) works fine — the provider connects, the ABI loads, eth_getCode returns bytecode (non-zero), and simple view calls (e.g., listingPrice()) decode correctly. The error only appears when calling fetchMarketItems (returns tuple[]).

preg_replace regex take too much from string, want to replace text inner [duplicate]

have a problem with preg_replace.
I have BBCodes and want them replace.
lets say i want to replace the attach bbcode with attachment id: 35318

String:

[ATTACH]35316[/ATTACH][ATTACH]35318[/ATTACH]
[ATTACH]35317[/ATTACH]

preg_replace:

preg_replace('/[ATTACH(.*)]35318[/ATTACH]/', '[ATTACH type="full" alt="test" width="250px"]35318[/ATTACH]', $input_lines);

it deletes

[ATTACH]35316[/ATTACH]

result:

[ATTACH type="full" alt="test" width="250px"]35318[/ATTACH]
[ATTACH]35317[/ATTACH]

need result:

 [ATTACH]35316[/ATTACH][ATTACH type="full" alt="test" width="250px"]35318[/ATTACH][ATTACH]35317[/ATTACH]

is there a solution with preg_replace to take inner replace from the 35318

my solution, but it is a workaround:
put whitespaces between closing attach and opening attach and then run preg_replace and after that remove whitespaces between closing attach and opening attach

Experiencing high loads for Apache/PHP-FPM site [closed]

Traditionally, the load average of our Alma Linux server running our Apache/PHP-FPM/MariaDB website has been 1-3. We’ve recently experienced some good press and it appears our server is getting more traffic and the load is sustaining at 4-6 with burst above 10. We use Cloudflare, when I turn on “Under Attack Mode”, which essentially puts up the page to verify visitors are human, it immediately subsides to back to traditional levels. I’ve been watching Apache server status and see the requests being processed jumps from 5-20 to above 50 and hits 100 causing the high loads and when I need to enable the setting in Cloudflare until it drops to acceptable loads. I can see the status in Cloudflare showing the number of requests on the rise as well when this happens and php-fpm status page shows maxed out active processes. If I increase max_children, the load just increases dramatically as active processes reach their max_children. We are a local newsroom, the high traffic usually traces back to a news story getting shared or picked up by a national company. We got some recent national press, I had to leave the Cloudflare protection on most of the day and week following, and it has been coming in waves since.

So, I am trying to determine if it is time to add another server and look at load balancing or if some optimization is what’s needed. Or both. We are running Apache 2.4.62, PHP-FPM 8.3.24 and MariaDB 10.11.14.

Looking at top it seems php-fpm may be the cause of the high load at 98% CPU for one process during periods of high loads and the rest of the php-fpm processes 10-40% with the MariaDB processlist showing little with no queries more than 0 time, I may have one pop in there for 2-3 seconds, but nothing more and I never see more than 20-25 sleep processes during the high load.

As far as php-fpm, here are the current pertinent settings with typical system info during high loads…

pm = ondemand
pm.max_children = 15
pm.process_idle_timeout = 10s;
pm.max_requests = 500

ATOP - alma1         2025/08/26  18:37:13         -----------------          10s elapsed
PRC |  sys    4.37s  | user  49.41s  |  #proc    189  |  #zombie    0 |  #exit     10  |
CPU |  sys      41%  | user    494%  |  irq       4%  |  idle     61% |  wait      1%  |
cpu |  sys       7%  | user     86%  |  irq       1%  |  idle      6% |  cpu003 w  0%  |
cpu |  sys       6%  | user     84%  |  irq       1%  |  idle      9% |  cpu004 w  0%  |
cpu |  sys       7%  | user     83%  |  irq       1%  |  idle      9% |  cpu001 w  0%  |
cpu |  sys       7%  | user     80%  |  irq       1%  |  idle     12% |  cpu005 w  0%  |
cpu |  sys       7%  | user     80%  |  irq       1%  |  idle     12% |  cpu002 w  0%  |
cpu |  sys       7%  | user     79%  |  irq       1%  |  idle     13% |  cpu000 w  0%  |
CPL |  avg1    9.03  | avg5    9.64  |  avg15   8.23  |  csw    81558 |  intr  104638  |
MEM |  tot    15.4G  | free  250.5M  |  buff   91.9M  |  slab  624.6M |  numnode    1  |
SWP |  tot   512.0M  | free    8.3M  |  swcac   5.9M  |  vmcom  16.1G |  vmlim   8.2G  |
PAG |  numamig    0  | migrate 14e3  |  swin       0  |  swout      0 |  oomkill    0  |
DSK |           sda  | busy      1%  |  read     151  |  write    517 |  avio 0.19 ms  |
NET |  transport     | tcpi   13312  |  tcpo   26862  |  udpi     891 |  udpo     891  |
NET |  network       | ipi    14203  |  ipo    19189  |  ipfrw      0 |  deliv  14203  |
NET |  eth0    ----  | pcki   14197  |  pcko   19173  |  si 3192 Kbps |  so   28 Mbps  |
NET |  lo      ----  | pcki      16  |  pcko      16  |  si    4 Kbps |  so    4 Kbps  |

    PID SYSCPU USRCPU  RDELAY  VGROW  RGROW   RDDSK  WRDSK S  CPUNR  CPU CMD         1/5
2064409  0.16s  8.07s   1.52s 112.8M  45.7M    5.1M     0B R      1  82% php-fpm
2036955  0.25s  3.31s   1.27s  -4.0M  -4.2M      0B     0B S      0  36% php-fpm
2035984  0.29s  3.26s   0.81s   6.0M 133.0M      0B     0B R      4  36% php-fpm
2032153  0.24s  3.16s   1.44s   2.0M   2.0M      0B     0B S      5  34% php-fpm
2032982  0.22s  3.06s   1.36s   8.0M   8.1M      0B     0B S      1  33% php-fpm
2036323  0.22s  2.95s   1.50s     0B 112.0K      0B     0B S      2  32% php-fpm
2036736  0.22s  2.86s   1.28s   2.0M   2.2M      0B     0B S      5  31% php-fpm
2063710  0.28s  2.62s   1.66s     0B 129.3M      0B     0B R      0  29% php-fpm
2039311  0.22s  2.67s   1.12s     0B     0B      0B     0B R      0  29% php-fpm
2035483  0.22s  2.65s   0.95s     0B     0B      0B     0B R      2  29% php-fpm
2033448  0.24s  2.57s   1.22s   4.0M   3.4M      0B     0B S      4  28% php-fpm
2032951  0.21s  2.57s   1.45s  -2.0M  -1.1M      0B     0B S      0  28% php-fpm
2031692  0.21s  2.41s   0.97s -40.2M -34.5M      0B     0B S      0  26% php-fpm
2032826  0.21s  2.38s   1.24s   2.0M   2.0M      0B     0B R      5  26% php-fpm
3480718  0.60s  1.63s   5m46s     0B  13.6M   16.0K   2.3M S      0  22% mariadbd
2064719  0.17s  1.49s   0.43s 841.9M 210.9M      0B     0B S      2  17% php-fpm

Server load: 9.38 9.71 8.25
Total accesses: 16713 - Total Traffic: 1.4 GB - Total Duration: 22404839
CPU Usage: u7.5 s2.7 cu15.16 cs5.47 - 1.77% CPU load
9.62 requests/sec - 0.8 MB/second - 90.0 kB/request - 1340.56 ms/request
29 requests currently being processed, 0 workers gracefully restarting, 67 idle workers

Seeing what is taking my memory, I have this script…

[root@alma1 ~]# cat apache_mem_usage.sh
#!/usr/bin/sh
ps -ylC httpd | awk '{x += $8;y += 1} END {print "Apache memory usage (MB): "x/1024; print "Average Apache Process Size (MB): "x/((y-1)*1024)}'
ps -ylC php-fpm | awk '{x += $8;y += 1} END {print "PHP-FPM memory usage (MB): "x/1024; print "Average PHP-FPM Process Size (MB): "x/((y-1)*1024)}'
ps -ylC mariadbd | awk '{x += $8;y += 1} END {print "MariaDB memory usage (MB): "x/1024}'
free
[root@alma1 ~]# ./apache_mem_usage.sh
Apache memory usage (MB): 279.188
Average Apache Process Size (MB): 27.9187
PHP-FPM memory usage (MB): 5103.15
Average PHP-FPM Process Size (MB): 318.947
MariaDB memory usage (MB): 6707.73
               total        used        free      shared  buff/cache   available
Mem:        16113200     9426012      307164      441444     7163324     6687188
Swap:         524284      516656        7628

Perhaps the PHP-FPM process memory usage is higher than it should be? The innodb_buffer_pool_size parameter for MariaDB is set to 6G and I found the query that shows it could possibly need to be 3 times that size or some db optimization may be needed…

MariaDB [(none)]> SELECT CEILING(Total_InnoDB_Bytes*1.6/POWER(1024,3)) RIBPS FROM (SELECT SUM(data_length+index_length) Total_InnoDB_Bytes FROM information_schema.tables WHERE engine='InnoDB') A;
+-------+
| RIBPS |
+-------+
|    18 |
+-------+

So I don’t believe I can give up any of that memory for PHP unless I reduce that number. The largest innodb table I have is 19 million rows that tracks ads and has been running for many years with 3 indexes…

MariaDB [wmnf_www]> SHOW TABLE STATUS LIKE 'wp_ad_tracker' G;
*************************** 1. row ***************************
            Name: wp_ad_tracker
          Engine: InnoDB
         Version: 10
      Row_format: Dynamic
            Rows: 19829074
  Avg_row_length: 52
     Data_length: 1047511040
 Max_data_length: 0
    Index_length: 1000275968
       Data_free: 4194304
  Auto_increment: 146764111
     Create_time: 2025-04-20 09:53:51
     Update_time: 2025-08-26 17:39:10
      Check_time: NULL
       Collation: utf8mb4_unicode_ci
        Checksum: NULL
  Create_options:
         Comment:
Max_index_length: 0
       Temporary: N

I’ll leave it at that for now, looking for pointers or recommendations on best way to proceed to get the loads reduced.

Using the SDK, cloud tasks are always created with default deadline, ignoring setDispatchDeadline

We are creating tasks using the following code with the SDK:

use GoogleCloudTasksV2ClientCloudTasksClient;
use GoogleCloudTasksV2HttpMethod;
use GoogleCloudTasksV2HttpRequest;
use GoogleCloudTasksV2OidcToken;
use GoogleCloudTasksV2Task;

...

$client = new CloudTasksClient();
$parent = $client->queueName(self::PROJECTE, self::REGIO, $this->cua);
            
$httpRequest = new HttpRequest();
$httpRequest->setHttpMethod($metode);
$httpRequest->setUrl(self::prepararUrl($url, $metode, $this->parametres ?? null));
$httpRequest->setHeaders(self::prepararHeaders($headers));
            
if ($parametres && in_array($metode, [HttpMethod::POST, HttpMethod::PUT, HttpMethod::PATCH])) {
    $httpRequest->setBody(http_build_query($parametres));
}
            
if ($this->cua === self::CUA_PERMISOS) {
     $oidcToken = new OidcToken();
     $oidcToken->setServiceAccountEmail(self::SERVICE_ACCOUNT);
     $oidcToken->setAudience(self::URL_SERVEI_WORKER);
     $httpRequest->setOidcToken($oidcToken);
}
            
$tasca = new Task();
$tasca->setHttpRequest($httpRequest);
$tasca->setDispatchDeadline((new GoogleProtobufDuration())->setSeconds(1800));
            
$request = (new GoogleCloudTasksV2CreateTaskRequest())->setParent($parent)->setTask($tasca);
$client->createTask($request);

This is creating tasks with deadlines of 600 seconds, ignoring the 1800 set on the request:
Log for the task created

Acording to the docs, the maximum value is 1800 (30 minutes) for Cloud Task dispatching an HTTP request.

We are using PHP 8.3 with these libraries:

{
  "google/apiclient": "^2.18",
  "google/cloud-storage": "^1.36",
  "google/cloud-logging": "^1.31",
  "google/cloud-error-reporting": "^0.22.7",
  "google/cloud-tasks": "^1.15"
}

Any insight on how/why this happens?

We tried passing a string directly instead of the Durationobject to the method Task::setDispatchDeadline, but the result has always been the same.

Unable to install composer, “Unable to load dynamic library ‘wincache'” [duplicate]

I’m trying to install Composer on my machine and I’ve downloaded the installer from getcomposer.com, but when I run it I get the error “The PHP exe file you specified did not run correctly” with the following program output:

PHP Warning: Module “ldap” is already loaded

PHP Warning: Module “mysqli” is already loaded

PHP Warning: PHP Startup: Unable to load dynamic library ‘wincache’ (tried: C:Program Filesphp8.3.9extwincache (The specified module could not be found), C:Program Filesphp8.3.9extphp_wincache.dll (The specified module could not be found))

It appears based on the output that the problem is with my wincache dll file, but I’ve checked in php8.3.9ext and there is a file called php_wincache.dll. For some reason, the installer doesn’t seem to recognize it. Does anyone know how I can resolve this issue and run the installer?

How to display WooCommerce orders in a custom frontend dashboard with filters and pagination? [closed]

I’m trying to build a custom frontend dashboard (for shop managers) where they can view and filter WooCommerce orders.
Here’s what I need:

  • Display orders in a table (order number, date, status, total, customer, actions).

  • Add filters by date range and order status.

  • Add pagination (so not all orders load at once).

  • Make sure the query is optimized and doesn’t slow down the site when there are thousands of orders.

I’m currently using WC_Order_Query with paginate => true, which works, but I’m not sure if this is the best way to handle performance and scalability.

My questions are:

  • What is the most efficient way to query and display WooCommerce orders in the frontend with filters and pagination?

  • Should I use WC_Order_Query, WP_Query, or maybe a custom SQL query for better performance?

  • Any best practices to avoid slowing down the dashboard when there are many orders?

<?php
defined('ABSPATH') || exit;

if (! is_user_logged_in() || ! current_user_can('manage_woocommerce')) {
    echo '<p>Accesso negato.</p>';
    return;
}

$start_date   = isset($_GET['start_date'])   ? esc_attr($_GET['start_date'])   : '';
$end_date     = isset($_GET['end_date'])     ? esc_attr($_GET['end_date'])     : '';
$status       = isset($_GET['order_status']) ? sanitize_text_field($_GET['order_status']) : '';

$per_page     = 10;
$current_page = max(1, get_query_var('paged', isset($_GET['paged']) ? intval($_GET['paged']) : 1));

$query_args = [
    'paginate'     => true,
    'limit'        => $per_page,
    'paged'        => $current_page,
    'orderby'      => 'date',
    'order'        => 'DESC',
    'status'       => array_keys(wc_get_order_statuses()),
];

// Date filter
if ($start_date && ! $end_date) {
    $query_args['date_created'] = '>=' . $start_date;
} elseif (! $start_date && $end_date) {
    $query_args['date_created'] = '<=' . $end_date;
} elseif ($start_date && $end_date) {
    $query_args['date_created'] = $start_date . '...' . $end_date;
}

// Status filter
if (! empty($status)) {
    $query_args['status'] = $status;
}

// Run query
$orders_data = (new WC_Order_Query($query_args))->get_orders();
$orders      = $orders_data->orders;
$max_pages   = $orders_data->max_num_pages;
$has_orders  = ! empty($orders);
?>

<!-- FILTER FORM -->
<form action="#" method="get" class="woocommerce-order-filter-form form-data-filter">
    <input type="hidden" name="tab" value="orders" />
    
    From
    <input class="date-input" type="date" name="start_date" value="<?php echo esc_attr($start_date); ?>">
    To
    <input class="date-input" type="date" name="end_date"   value="<?php echo esc_attr($end_date); ?>">

    <select name="order_status" class="status-select">
        <option value=""><?php esc_html_e('All statuses', 'woocommerce'); ?></option>
        <?php foreach (wc_get_order_statuses() as $slug => $label): ?>
            <?php $pure_slug = str_replace('wc-', '', $slug); ?>
            <option value="<?php echo esc_attr($pure_slug); ?>" <?php selected($status, $pure_slug); ?>>
                <?php echo esc_html($label); ?>
            </option>
        <?php endforeach; ?>
    </select>

    <input class="date-submit" type="submit" value="<?php esc_attr_e('Filter', 'woocommerce'); ?>">
    <?php if ($start_date || $end_date || $status): ?>
        <a class="button reset" href="?tab=orders"><?php esc_html_e('Reset', 'woocommerce'); ?></a>
    <?php endif; ?>
</form>

<!-- ORDERS TABLE -->
<?php if ($has_orders): ?>
    <table class="gestore-tabella-ordini cpa-dasboard-table">
        <thead>
            <tr>
                <th>Order</th>
                <th>Date</th>
                <th>Status</th>
                <th>Total</th>
                <th>Customer</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($orders as $order): ?>
                <?php
                if (! is_a($order, 'WC_Order')) {
                    continue;
                }

                $status_code  = $order->get_status();
                $status_map   = [
                    'pending'        => ['label' => 'Pending',      'icon' => 'fa-clock'],
                    'processing'     => ['label' => 'Processing',   'icon' => 'fa-gear'],
                    'on-hold'        => ['label' => 'On hold',      'icon' => 'fa-spinner'],
                    'completed'      => ['label' => 'Completed',    'icon' => 'fa-circle-check'],
                    'cancelled'      => ['label' => 'Cancelled',    'icon' => 'fa-circle-xmark'],
                    'refunded'       => ['label' => 'Refunded',     'icon' => 'fa-arrow-rotate-left'],
                    'failed'         => ['label' => 'Failed',       'icon' => 'fa-triangle-exclamation'],
                    'checkout-draft' => ['label' => 'Draft',        'icon' => 'fa-spinner'],
                ];
                $status_data = $status_map[ $status_code ] ?? [
                    'label' => ucfirst($status_code),
                    'icon'  => 'fa-question-circle',
                ];
                ?>
                <tr class="woocommerce-orders-table__row status-<?php echo esc_attr($status_code); ?>">
                    <th scope="row">
                        <span class="order-number">#<?php echo esc_html($order->get_order_number()); ?></span>
                    </th>
                    <td>
                        <time datetime="<?php echo esc_attr($order->get_date_created()->date('c')); ?>">
                            <?php echo esc_html(wc_format_datetime($order->get_date_created())); ?>
                        </time>
                    </td>
                    <td>
                        <span class="status-text status-<?php echo esc_attr($status_code); ?>">
                            <i class="fa-solid <?php echo esc_attr($status_data['icon']); ?>"></i>
                            <?php echo esc_html($status_data['label']); ?>
                        </span>
                    </td>
                    <td>
                        <?php echo $order->get_formatted_order_total(); ?>
                    </td>
                    <td>
                        <?php echo esc_html($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()); ?>
                    </td>
                    <td>
                        <a href="/dashboard/?dettaglio_ordine=<?php echo esc_attr($order->get_id()); ?>" class="cpa-btn-secondary">
                            <i class="fa-solid fa-magnifying-glass"></i>
                        </a>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

    <!-- PAGINATION -->
    <?php if ($max_pages > 1): ?>
        <div class="woocommerce-pagination woocommerce-pagination--numeric woocommerce-Pagination">
            <?php
            $base_url = remove_query_arg('paged');
            ?>
            <?php if ($current_page > 1): ?>
                <a class="woocommerce-button woocommerce-button--previous button"
                   href="<?php echo esc_url(add_query_arg('paged', $current_page - 1, $base_url)); ?>">
                    &larr; Previous
                </a>
            <?php endif; ?>

            <?php for ($i = 1; $i <= $max_pages; $i++): ?>
                <?php if ($i === $current_page): ?>
                    <span class="page-number current"><?php echo $i; ?></span>
                <?php else: ?>
                    <a class="page-number" href="<?php echo esc_url(add_query_arg('paged', $i, $base_url)); ?>">
                        <?php echo $i; ?>
                    </a>
                <?php endif; ?>
            <?php endfor; ?>

            <?php if ($current_page < $max_pages): ?>
                <a class="woocommerce-button woocommerce-button--next button"
                   href="<?php echo esc_url(add_query_arg('paged', $current_page + 1, $base_url)); ?>">
                    Next &rarr;
                </a>
            <?php endif; ?>
        </div>
    <?php endif; ?>

<?php else: ?>
    <?php wc_print_notice('No orders found.', 'notice'); ?>
<?php endif; ?>

When i submit FormData using Json/Ajax it is not going through [closed]

Im trying to add profile photo to my users but when im trying to click submit button it is not going through.

Here is my Json


function getUserFormData(form) {
    return  {
        action: "addUser",
        user: {
            user_id: User : null,
            email: form['email'].value,
            username: form['username'].value,
            password: Util.hash(form['password'].value),
            password_confirmation: Util.hash(form['password_confirmation'].value),
            profile_image: form['profile_image'].value
        }
    };
}

AS.Http.submituser = function (form, data, success, error, complete) {
    AS.Util.removeErrorMessages();

    var $submitBtn = $(form).find("button[type=submit]");
    var $fileupload = $(data).prop('profile_image');
    var formData = new FormData();
    formData.append('file', $fileupload);

    if ($submitBtn) {
        AS.Util.loadingButton($submitBtn, $submitBtn.data('loading-text') || $_lang.working);
    }

    $.ajax({
        url: "/Ajax.php",
        cache: false,
        contentType: false,
        processData: false,
        type: "POST",
        dataType: "json",
        data: data,
        success: function (response) {
            form.reset();

            if (typeof success === "function") {
                success(response);
            }
        },
        error: error || function (errorResponse) {
            AS.Util.showFormErrors(form, errorResponse);
        },
        complete: complete || function () {
            if ($submitBtn) {
                AS.Util.removeLoadingButton($submitBtn);
            }
        }
    });
};

Here is the Back End

    public function add(array $data)
    {
        if ($errors = $this->registrator->validateUser($data, false)) {
            ASResponse::validationError($errors);
        }
        // Handle secure profile image upload
        $files = $data['profile_image'];
        $targetDirectory = "../assets/img/usersprofile/";
        $imageFileType = strtolower(pathinfo($files["profile_image"]["name"], PATHINFO_EXTENSION));

        // Generate a unique image filename: complete_name_uniqueID.extension
        $username = $data['username'];
        $safeName = preg_replace('/[^A-Za-z0-9]/', '_', $username); // Remove special chars
        $uniqueID = uniqid();
        $imageName = "{$safeName}_{$uniqueID}.{$imageFileType}";
        $targetFile = $targetDirectory . $imageName;

        // Validate image file
        $validMimeTypes = ['image/jpeg', 'image/png', 'image/gif'];
        $check = getimagesize($files["profile_image"]["tmp_name"]);
        if ($check === false || !in_array($check['mime'], $validMimeTypes)) {
            throw new Exception("Invalid image file format.");
        }

        // Check file size (max 2MB)
        if ($files["profile_image"]["size"] > 2000000) {
            throw new Exception("File size exceeds the 2MB limit.");
        }

        // Restrict executable file uploads
        if (preg_match('/.(php|html|htm|js|exe|sh)$/i', $files["profile_image"]["name"])) {
            throw new Exception("Invalid file type.");
        }

        // Ensure upload directory is safe
        if (!is_dir($targetDirectory) && !mkdir($targetDirectory, 0755, true)) {
            throw new Exception("Failed to create upload directory.");
        }

        // Move uploaded file
        if (!move_uploaded_file($files["profile_image"]["tmp_name"], $targetFile)) {
            throw new Exception("Error uploading the image.");
        }

        $this->db->insert('users', [
            'email' => $data['email'],
            'username' => $data['username'],
            'password' => $this->hashPassword($data['password']),
            'profile_image' => $imageName
        ]);



        Response::success(["message" => trans("user_added_successfully")]);
    }

I tried to append file but unfortunately still nothing happen. i cant see what is error because it is not showing.

Permission of folder it read/writable.

I dont know if the code is right, could you please help me!