Cutting through the static – Larry Garfield

Cutting through the static

Static methods and properties have a storied and controversial history in PHP. Some love them, some hate them, some love having something to fight about (naturally).

In practice, I find them useful in very narrow situations. They’re not common, but they do exist. Today, I want to go over some guidelines on when PHP developers should, and shouldn’t, use statics.

In full transparency, I will say that the views expressed here are not universal within the PHP community. They do, however, represent what I believe to be the substantial majority opinion, especially among those who are well-versed in automated testing.

Continue reading this post on PeakD.

29 November 2023 – 4:28pm

Automating the backslash prefixing for native PHP function calls – Raphael Stolt

After reading the blog post Why does a backslash prefix improve PHP function call performance by Jeroen Deviaene I was looking for a way to automate it for the codebase of the Lean Package Validator, to shave off some miliseconds for it’s CLI. The PHP Coding Standards Fixer has a rule named native_function_invocation which does the very exact task.

Configuring the PHP Coding Standards Fixer

<?php use PhpCsFixer\Config;
use PhpCsFixer\Finder; $finder = Finder::create() ->in([__DIR__, __DIR__ . DIRECTORY_SEPARATOR . 'tests']); $rules = [ 'psr_autoloading' => false, '@PSR2' => true, 'phpdoc_order' => true, 'ordered_imports' => true, 'native_function_invocation' => [ 'include' => ['@internal'], 'exclude' => ['file_put_contents'] ]
]; $cacheDir = \getenv('HOME') ? \getenv('HOME') : __DIR__; $config = new Config(); return $config->setRules($rules) ->setFinder($finder) ->setCacheFile($cacheDir . '/.php-cs-fixer.cache');

To make this rule executeable I needed to add the –allow-risky=yes option to the PHP Coding Standards Fixer calls in the two dedicated Composer scripts shown next.

"scripts": { "lpv:test": "phpunit", "lpv:test-with-coverage": "export XDEBUG_MODE=coverage && phpunit --coverage-html coverage-reports", "lpv:cs-fix": "php-cs-fixer --allow-risky=yes fix . -vv || true", "lpv:cs-lint": "php-cs-fixer fix --diff --stop-on-violation --verbose --dry-run --allow-risky=yes", "lpv:configure-commit-template": "git config --add commit.template .gitmessage", "lpv:application-version-guard": "php bin/application-version --verify-tag-match=bin", "lpv:application-phar-version-guard": "php bin/application-version --verify-tag-match=phar", "lpv:static-analyse": "phpstan analyse --configuration phpstan.neon.dist", "lpv:validate-gitattributes": "bin/lean-package-validator validate"

After running the lpv:cs-fix Composer script the first time the test of the system under test started failing due to file_put_contents being prefixed with a backslash, so I had to exclude it as shown in the PHP Coding Standards Fixer configuration above.

Using JSX on the server as a template engine – Evert Pot

The React/Next.js ecosystem is spinning out of control in terms of magic and complexity.
The stack has failed to stay focused and simple, and it’s my belief
that software stacks that are too complex and magical must eventually fail,
because as sensibilities around software design change they will be unable to
adapt to those changes without cannibalizing their existing userbase.

So while React/Next.js may be relegated to the enterprise and legacy systems in
a few years, they completely transformed front-end development and created ripple
effects in many other technologies. One of many great ideas stemming from this
stack is JSX. I think JSX has a chance to stay relevant and useful beyond

One of it’s use-cases is for server-side templating. I’ve been using JSX as a
template engine to replace template engines like EJS and
Handlebars, and more than once people were surprised this was possible
without bulky frameworks such as Next.js.

So in this article I’m digging into what JSX is, where it comes from and how one
might go about using it as a simple server-side html template engine.

What is JSX?

JSX is an extension to the Javascript language, and was introduced with React.
It usually has a .jsx extension and it needs to be compiled to Javascript.
Most build tools people already use, like ESbuild, Babel, Vite, etc. all
support this natively or through a plugin.
Typescript also natively supports it, so if you use Typescript you can just start
using it without adding another tool.

It looks like this:

const foo = <div> <h1>Hello world!</h1> <p>Sup</p>

As you can see here, some html is directly embedded into Javascript, without
quotes. It’s all syntax. It lets you use the full power of Javascript, such
as variables and loops:

const user = 'Evert';
const todos = [ 'Wash clothes', 'Do dishes',
]; const foo = <div> <h1>Hello {evert}</div> <ul> { todo => <li>todo</li>)} </ul>

It has a convention to treat tags that start with a lowercase character such
as <h1> as output, but if the tag starts with an uppercase character,
it’s a component, which usually is represented by a function:

function HelloWorldComponent(props) { 

Truncated by Planet PHP, read more at the original (another 32023 bytes)

Announcing Crell/Serde 1.0.0 – Larry Garfield

Announcing Crell/Serde 1.0.0

Submitted by Larry on 9 November 2023 – 7:39pm

I am pleased to announce that the trio of libraries I built while at TYPO3 have now reached a fully stable release. In particular, Crell/Serde is now the most robust, powerful, and performant serialization library available for PHP today!

Serde is inspired by the Rust library of the same name, and driven almost entirely by PHP Attributes, with entirely pure-function object-oriented code. It’s easy to configure, easy to use, and rock solid.

Xdebug Update: October 2023 – Derick Rethans

Xdebug Update: October 2023

In this monthly update I explain what happened with Xdebug development in the past month. These are normally published on the first Tuesday on or after the 5th of each month.

Patreon and GitHub supporters will get it earlier, around the first of each month.

You can become a patron or support me through GitHub Sponsors. I am currently 35% towards my $2,500 per month goal, which is set to allow continued maintenance of Xdebug.

If you are leading a team or company, then it is also possible to support Xdebug through a subscription.

In the last month, I spend around 32 hours on Xdebug, with 25 hours funded.

Towards Xdebug 3.3

In last month’s update I explained that I was investigating whether Xdebug can make use of PHP’s Observer API. It turns out that it can be used to intercept function calls, but only include or require calls if the included files contain code, and not just class definitions. As Xdebug treats include and friends as actual function calls, I can unfortunately not solely rely on the Observer API.

In the wake of checking out the Observer API, I also thought I should have a look at some performance improvements. For example, I noticed that Xdebug would always collect local variables with each function call. This is only really needed when showing local variables, in stack traces, or through the step debugger.

Another optimisation that I worked on was to optimise the way how function breakpoints are checked against. These breakpoints trigger when a function gets called, or returned from. This is not a feature that many people often use, but Xdebug would always do some work to be able to compare the configured breakpoints against a normalised function name reference.

These two optimisations together resulted in a 20% reduction in CPU instructions (roughly equivalent to execution time) with the front page of WordPress’ demo site.

The third optimisation that I worked is related to file/line breakpoints. Xdebug would evaluate whether an IDE has set a line breakpoint on the current line. For this, it had to loop over all the existing breakpoints and compare them. Each additional breakpoint would be checked after every statement, meaning that the number of breakpoints affected the running time of the script.

My optimisation alleviates this by moving the check on whether line breakpoints exist for a function or method to the function call itself. If no breakpoints are set in the whole function, then Xdebug skips the check for line breakpoints after each statement. This shifts the factor of performance loss for having line breakpoints from the number of statements to the number of function calls. This shift results in a roughly 25% performance boost with only four line breakpoints enabled.

After attending IPC and speaking to fellow Xdebug users, a question came up about long running scripts. Right now, Xdebug’s step debugger can only be activated when the script starts or by calling xdebug_connect_to_client(). Breakpoints can also only be configured when Xdebug is waiting for a command to continue a script (after a step, an existing breakpoint, or at the start of the script). While a script is running, you can not interrupt the execution to break, or add new breakpoints.

This let me to experiment with a control socket, currently only available on Linux. Through this socket you can then ask Xdebug for information, or request a breakpoint so that you can then use your IDE to add more breakpoints, or inspect the current state.

At the moment, I have implemented the “show me some information” feature, which allows me to show the running PHP scripts, with PID, memory usage (in kb), running time, and Xdebug version. The xdebug command line tool allo

Truncated by Planet PHP, read more at the original (another 2513 bytes)

PHP 8.3.0 RC 6 available for testing – PHP: Hypertext Preprocessor

The PHP team is pleased to announce the release of PHP 8.3.0, RC 6. This is the sixth and final release candidate, continuing the PHP 8.3 release cycle, the rough outline of which is specified in the PHP Wiki. For source downloads of PHP 8.3.0, RC 6 please visit the download page. Please carefully test this version and report any issues found in the bug reporting system. Please DO NOT use this version in production, it is an early test version. For more information on the new features and other changes, you can read the NEWS file or the UPGRADING file for a complete list of upgrading notes. These files can also be found in the release archive. The next release will be the production-ready, general availability release, planned for 23 November 2023. The signatures for the release can be found in the manifest or on the QA site. Thank you for helping us make PHP better.

Flamboyant Flamegraphs – Derick Rethans

Flamboyant Flamegraphs

In this article, I am showing you how to make a flamegraph, a new feature in Xdebug 3.3.

Flamegraphs are an interesting way of showing where an application spends a lot of time.

To show you the functionality, I will be using Xdebug’s own website, which I run locally at port 9874.

First of all, we need to configure Xdebug to make our flamegraphs. We do that in a configuration file. With php --ini I find out which file to use:

Configuration File (php.ini) Path: /usr/local/php/8.2dev/lib
Loaded Configuration File: /usr/local/php/8.2dev/lib/php.ini
Scan for additional .ini files in: /usr/local/php/8.2dev/lib/conf.d
Additional .ini files parsed: /usr/local/php/8.2dev/lib/conf.d/20-mongodb.ini,

If you are running Apache or Nginx, I would suggest you use phpinfo() output in the browser to find the same information instead.

I have a specific Xdebug INI file called zzz-xdebug.ini. Its contents are currently:

Flamegraphs are part of Xdebug’s tracing functionality, which we need to enable by changing the xdebug.mode line to:


The tracing functionality supports multiple formats. The flamegraph is number three, so we need to set that as well by adding:


By default, Xdebug Tracer will put files into the /tmp directory, and use a hash of the current working directory to create a trace file name. We want distinct flamegraphs for each URL, so we need to change that by setting:


We start all files with trace., and then we use %R to configure to use the URI. Xdebug also supports many other formatting specifiers.

By default, all file names will also be postfixed by .xt.gz.

After making INI changes, you need to restart the web server.

To initiate the tracer, I use an Xdebug Helper browser extension available for Chrome, Firefox, and other browsers.

I click on the debug icon and then on trace:

After requesting the home page, and documentation page, Xdebug’s tracer created the following files in the /tmp directory:

derick@gargleblaster:~$ ls -l /tmp/trace.*
-rw-r--r-- 1 derick derick 123 Sep 26 03:31 /tmp/trace..05d7ef.xt.gz
-rw-r--r-- 1 derick derick 2560 Sep 25 16:55 /tmp/trace._core2_css.xt.gz
-rw-r--r-- 1 derick derick 3550 Sep 25 16:55 /tmp/trace._docs_.xt.gz
-rw-r--r-- 1 derick derick 2419 Sep 25 16:55 /tmp/trace._fonts_IBMPlexSans-RegularItalic-Latin1_woff2.xt.gz
-rw-r--r-- 1 derick derick 2474 Sep 25 16:55 /tmp/trace._images_logos_11com7_svg.xt.gz
-rw-r--r-- 1 derick derick 2507 Sep 25 16:55 /tmp/trace._images_logos_io_svg.xt.gz
-rw-r--r-- 1 derick derick 2530 Sep 25 16:55 /tmp/trace._images_logos_private-packagist_svg.xt.gz
-rw-r--r-- 1 derick derick 2455 Sep 25 16:55 /tmp/trace._images_logos_typo3_svg.xt.gz
-rw-r--r-- 1 derick derick 2523 Sep 25 16:55 /tmp/trace._images_logos_xdebug-cloud_svg.xt.gz
-rw-r--r-- 1 derick derick 6165 Sep 25 16:55 /tmp/trace._.xt.gz 

Because we go through our PHP router process, there are also files for images and fonts.

The important ones are:

-rw-r--r-- 1 derick derick 3550 Sep 25 16:55 /tmp/trace._docs_.xt.gz
-rw-r--r-- 1 derick derick 6165 Sep 25 16:55 /tmp/trace._.xt.gz 

The contents of these files look like:

{main};require_once;require_once 3046
{main};require_once;ComposerAutoloaderInit7d176ec022516f68e20dcb88554529a8::getLoader;require 7043
{main};require_once;ComposerAutoloaderInit7d176ec022516f68e20dcb88554529a8::getLoader;spl_autoload_register 9408
{main};require_once;ComposerAutoloaderInit7d176ec022516f68e20dcb88554529a8::getLoader;ComposerAutoloaderInit7d176ec022516f68e20dcb88554529a8::loadClassLoader;require 3176
{main};require_once;ComposerAutoloaderInit7d176ec022516f68e20dcb88554529a8::getLoader;ComposerAutoloaderInit7d176ec022516f68e20dcb88554529a8::loadClassLoader 41368
{main};require_once;ComposerAutoloaderInit7d176ec022516f68e20dcb88554529a8::getLoader;dirname 6061

Truncated by Planet PHP, read more at the original (another 1782 bytes)