In this blog, we discuss the results of our 2022 PHP Landscape Report and offer projections for the future of PHP.
Month: March 2022
Memory Malfeasance – Derick Rethans
Memory Malfeasance
A while ago I started getting weird crashes on my desktop machine — Gargleblaster. Once in a while, PHP, or Node, would crash. And browser tabs kept turning blank, with Firefox crashing altogether once in a while too.
At first I thought there was some memory corruption in a system library, but neither valgrind or GDB would show any issues — if the problem could be reproduced at all. It was also very random, but the problem went away for a short while after a reboot.
I suspected the worst: Broken memory.
In the past I had used tools like memtest86
, and memtest86+
— both available as packages on my Debian system. There are some complications with both of these on newer UEFI BIOS systems. This meant that when I tried them, the system would not even boot. A new version of memtest86+
was supposed to fix this, but that did not work either for me.
I decided to live with it for a while, but after another total loss of tabs (oh dear!), I stumbled upon a different tool: PCMemTest. This did boot, but their documentation page says “The UHCI USB controller is not yet supported”, which is needed for USB keyboards.
I was happily surprised that Debian’s APT repository also included a package for this memory testing tool. After I installed it, I rebooted my machine to see what it would say. The result:

PCMemTest allows you to create a configuration line for the Grub configuration which the Linux kernel uses while booting up to exclude certainly parts of physical memory from being used. However, without the USB keyboard working, I could not not navigate to that feature.
Then I read that the kernel itself also has a memory test tool built in: the memtest kernel parameter.
To include the memory test when the system boots, update the GRUB_CMDLINE_LINUX_DEFAULT
line in /etc/default/grub
to:
GRUB_CMDLINE_LINUX_DEFAULT="quiet pcie_aspm=off memtest=4"
And then run update-grub
.
Now when the system starts, the kernel will run a memory test and automatically exclude any memory that it finds not working.
On my system this looks in the dmesg
output like:
[ 0.000000] early_memtest: # of tests: 4 [ 0.000000] 0x0000000000100000 - 0x0000000001000000 pattern aaaaaaaaaaaaaaaa [ 0.000000] 0x0000000001020000 - 0x0000000004000000 pattern aaaaaaaaaaaaaaaa [ 0.000000] 0x000000000401e000 - 0x0000000009df0000 pattern aaaaaaaaaaaaaaaa … [ 0.000000] 0x0000000100000000 - 0x0000000180000000 pattern 5555555555555555 [ 0.000000] ------------[ cut here ]------------ [ 0.000000] Bad RAM detected. Use memtest86+ to perform a thorough test and the memmap= parameter to reserve the bad areas. … [ 0.000000] 5555555555555555 bad mem addr 0x000000016dbc8450 - 0x000000016dbc8458 reserved [ 0.000000] 0x000000016dbc8458 - 0x0000000180000000 pattern 5555555555555555 [ 0.000000] 0x0000000180410000 - 0x0000000727200000 pattern 5555555555555555 [ 0.000000] 0x000000072980d000 - 0x000000107f300000 pattern 5555555555555555 [ 0.000000] 0x0000000000100000 - 0x0000000001000000 pattern ffffffffffffffff … [ 0.000000] 0x000000072980d000 - 0x000000107f300000 pattern 0000000000000000
The line bad mem addr 0x000000016dbc8450 - 0x000000016dbc8458 reserved
is saying that the kernel excluded that section of memory because it found it to be broken.
Since I booted my system 16 days ago, I have no longer seen any unexplained crashes. Yay!
At some point I will need to replace this memory, if I find out which of the four memory modules it is. That is a job for some other time.
Breaking RSS Links – Jordi Boggiano
Sorry for the spam but I’m about to break links on the internet and I feel bad.
I am finally ready to migrate away from my home-grown-CMS-built-in-2007 to a static site generator, and while I can keep most things running the feed URLs will just have to go.
If you happen to be still be using RSS (high five fellow old person), and also subscribed to this blog, please update your subscription URL to: https://seld.be/feed.atom
PHP Internals News: Episode 100: Sealed Classes – Derick Rethans
PHP Internals News: Episode 100: Sealed Classes
In this episode of “PHP Internals News” I talk with Saif Eddin Gmati (Website, Twitter, GitHub) about the “Sealed Classes” RFC that he has proposed.
The RSS feed for this podcast is https://derickrethans.nl/feed-phpinternalsnews.xml, you can download this episode’s MP3 file, and it’s available on Spotify and iTunes. There is a dedicated website: https://phpinternals.news
Transcript
- Derick Rethans 0:14
-
Hi, I’m Derick. Welcome to PHP internals news, the podcast dedicated to explaining the latest developments in the PHP language. This is episode 100. Today I’m talking with Saif Eddin Gmati about the sealed classes RFC that they’re proposing. Saif, would you please introduce yourself?
- Saif Eddin Gmati 0:31
-
Hello, my name is Saif Eddin Gmati. I work as a Senior programmer at Les-Tilleuls.coop. I’m an open source enthusiast and contributor.
- Derick Rethans 0:39
-
Let’s dive straight into this RFC. What is the problem that you’re trying to solve with it?
- Saif Eddin Gmati 0:43
-
Sealed classes just like enums and tagged unions allow developers to define their data models in a way where invalid state becomes less likely. It also eliminates the need to handle unknown subtypes for a specific model, as using sealed classes to define models gives us an idea on what child types would be available at run time. Sealing also provides us with a way for restricting inheritance or the use of a specific trait. For example, if we look at logger trait from the PSR log package that could be sealed to logger interface. This way, we ensure that every use of this trait is coming from a logger not from any other class.
- Derick Rethans 1:24
-
I’m just reading through this RFC tomorrow, again, and something I didn’t pick up on reading to it last time. It states that PHP already has sort of two sealed classes.
- Unknown Speaker 1:35
-
Yes, the throwable class in PHP can only be implemented by extending either error or exception. The same applies for DateTime interface, which can only be implemented by extending DateTime class or DateTime Immutable class.
- Derick Rethans 1:52
-
Because PHP itself doesn’t allow you to implement either throwable or DateTimeInterface. I haven’t quite realized that that these are also sealed classes really. What is sort of the motivation behind wanting to introduce sealed classes?
- Unknown Speaker 2:06
-
The main motivation for this feature comes from Hack the programming language. Hack contains a lot of interesting type concepts that I think personally, PHP could benefit from and sealed classes is one of those concepts.
- Derick Rethans 2:18
-
What kind of syntax are you proposing?
- Saif Eddin Gmati 2:21
-
The syntax I’m proposing actually there is three syntax options for the RFC currently, but the main syntax is inspired by both Hack and Java. It’s more similar to the syntax used in Java as Hack uses attributes. Personally, I have been I guess, using attributes from the start as I personally see sealing and finalizing similar as both effects how inheritance work for a specific class. Having sealed implemented as an attribute while final uses a keyword brings more inconsistency into the language which is why I have decided not to include attributes as a syntax option.
- Derick Rethans 2:56
-
In my opinion, attributes shouldn’t be used for any kind of syntax things. What they s
Truncated by Planet PHP, read more at the original (another 13608 bytes)
Run Laravel 9 on Docker in 2022 [Tutorial Part 4.3] – Pascal Landau
In this third subpart of the fourth part of this tutorial series on developing PHP on Docker we will
install Laravel and make sure our setup works for Artisan Commands, a Redis Queue and Controllers
for the front end requests.
All code samples are publicly available in my
Docker PHP Tutorial repository on github.
You find the branch for this tutorial at
part-4-3-run-laravel-9-docker-in-2022
Published parts of the Docker PHP Tutorial
- Setting up PHP, PHP-FPM and NGINX for local development on Docker
(2018-07-08) - Setting up PhpStorm with Xdebug for local development on Docker
(2018-08-06) - Structuring the Docker setup for PHP Projects
(2019-05-20) - Docker from scratch for PHP 8.1 Applications in 2022
(2022-03-21) - PhpStorm, Docker and Xdebug 3 on PHP 8.1 in 2022
(2022-03-22) - Run Laravel 9 on Docker in 2022
(2022-03-23)
If you want to follow along, please subscribe to the RSS feed
or via email
to get automatic notifications when the next part comes out 🙂
Table of contents
- Introduction
- Install extensions
- Install Laravel
- Update the PHP POC
- Makefile updates
- Running the POC
- Wrapping up
Introduction
The goal of this tutorial is to run the
PHP POC from part 4.1
using Laravel as a framework instead of “plain PHP”.
We’ll use the newest version of Laravel (Laravel 9) that was
released at the beginning of February 2022.
Install extensions
Before Laravel can be installed, we need to add the necessary extensions of the framework (and all
its dependencies) to the php-base
image:
# File: .docker/images/php/base/Dockerfile # ... RUN apk add --update --no-cache \ php-curl~=${TARGET_PHP_VERSION} \
Install Laravel
We’ll start by
creating a new Laravel project with composer
composer create-project --prefer-dist laravel/laravel /tmp/laravel "9.*" --no-install --no-scripts
The files are added to /tmp/laravel
because
composer projects cannot be created in non-empty folders
, so we need to create the project in a temporary location first and move it afterwards.
Since I don’t have PHP 8 installed on my laptop, I’ll execute the command in the application
docker container via
make execute-in-container DOCKER_SERVICE_NAME="application" COMMAND='composer create-project --prefer-dist laravel/laravel /tmp/laravel "9.*" --no-install --no-scripts'
and then move the files into the application directory via
rm -rf public/ tests/ composer.* phpunit.xml
make ex
Truncated by Planet PHP, read more at the original (another 23527 bytes)
PhpStorm, Docker and Xdebug 3 on PHP 8.1 in 2022 [Tutorial Part 4.2] – Pascal Landau
In this second subpart of the fourth part of this tutorial series on developing PHP on Docker we
will setup our local development environment to be used by PhpStorm and Xdebug. We will also
ensure that we can run PHPUnit tests from the command line as well as from PhpStorm and throw
the tool strace
into the mix for debugging long running processes.
All code samples are publicly available in my
Docker PHP Tutorial repository on github.
You find the branch for this tutorial at
part-4-2-phpstorm-docker-xdebug-3-php-8-1-in-2022
Published parts of the Docker PHP Tutorial
- Setting up PHP, PHP-FPM and NGINX for local development on Docker
(2018-07-08) - Setting up PhpStorm with Xdebug for local development on Docker
(2018-08-06) - Structuring the Docker setup for PHP Projects
(2019-05-20) - Docker from scratch for PHP 8.1 Applications in 2022
(2022-03-21) - PhpStorm, Docker and Xdebug 3 on PHP 8.1 in 2022
(2022-03-22) - Run Laravel 9 on Docker in 2022
(2022-03-23)
If you want to follow along, please subscribe to the RSS feed
or via email
to get automatic notifications when the next part comes out 🙂
Table of contents
Introduction
This article is mostly an update of
Setting up PhpStorm with Xdebug for local development on Docker
but will also cover the “remaining cases” of debugging php-fpm and php worker processes.
We will still rely on an always-running docker setup that we connect to via an SSH Configuration
instead of using the
built-in docker-compose capabilities
as I feel it’s closer to what we do in CI / production. However, we will not use SSH keys
any longer but simply authenticate via password. This reduces complexity and removes any
pesky warnings regarding “SSH keys being exposed in a repository”.
Install Tools
Install composer
Composer is installed by pulling
the official composer docker image and simply “copying” the
composer executable over to the base php image. In addition, composer needs the extensions
mbstring
and phar
# File: .docker/images/php/base/Dockerfile ARG ALPINE_VERSION
ARG COMPOSER_VERSION
FROM composer:${COMPOSER_VERSION} as composer
FROM al
Truncated by Planet PHP, read more at the original (another 23988 bytes)
Docker from scratch for PHP 8.1 Applications in 2022 [Tutorial Part 4.1] – Pascal Landau
In the fourth part of this tutorial series on developing PHP on Docker we will revisit the previous
tutorials and update some things to be up-to-date in 2022. The article will be split in 3
subparts:
- Part 4.1: Update the code structure (this article)
- we’ll also introduce three new containers (PHP workers, MySQL and redis) and add a small proof
of concept to tie all containers together
- we’ll also introduce three new containers (PHP workers, MySQL and redis) and add a small proof
- Part 4.2: Add the tools for local development (
PhpStorm, Docker and Xdebug 3 on PHP 8.1 in 2022,
available at 2022-03-22)- make the setup work with PhpStorm, including the ability to execute phpunit tests and run
xdebug for all php containers (application, fpm and php workers)
- make the setup work with PhpStorm, including the ability to execute phpunit tests and run
- Part4.3: Include Laravel (
Run Laravel 9 on Docker in 2022,
available at 2022-03-23)- refactor the code to use Commands, Controllers, Queues, etc.
All code samples are publicly available in my
Docker PHP Tutorial repository on github.
You find the branch for this tutorial at
part-4-1-docker-from-scratch-for-php-applications-in-2022
Published parts of the Docker PHP Tutorial
- Setting up PHP, PHP-FPM and NGINX for local development on Docker
(2018-07-08) - Setting up PhpStorm with Xdebug for local development on Docker
(2018-08-06) - Structuring the Docker setup for PHP Projects
(2019-05-20) - Docker from scratch for PHP 8.1 Applications in 2022
(2022-03-21) - PhpStorm, Docker and Xdebug 3 on PHP 8.1 in 2022
(2022-03-22) - Run Laravel 9 on Docker in 2022
(2022-03-23)
If you want to follow along, please subscribe to the RSS feed
or via email
to get automatic notifications when the next part comes out 🙂
Table of contents
Introduction
If you have read the previous
tutorial Structuring the Docker setup for PHP Projects
you might encounter some significant changes. The tutorial was published over 2 years ago,
Docker has evolved and I have learned more about it. Plus, I gathered practical
experience (good and bad) with the previous setup. I would now consider most of the points under
Fundamentals on building the containers
as eith
Truncated by Planet PHP, read more at the original (another 34153 bytes)
Reasons why abolishing DST in the US will be worse for users and developers – Evert Pot
Daylight savings time is hated by many, and twice per year a discussion
reignites to get rid of it. Lot of folks feel this is a great idea. This year
this decision seems especially close in the US. If this law passes, it
will probably also change where I live .
No doubt there’s lots of benefits and advantages to this, I don’t want to
dispute that. This is also not an endorsement against that change, but I do
however want to bring light to at least one disadvantage:
The timezone change was for a lot of developers a twice-per-year reminder
that we need to use timezone databases and libraries.
This is useful, because every year many countries change their timezone
rules. This means that if you schedule something in the future, say.. 2pm 6
months from, you don’t know yet with absolute certainty what UTC timestamp
this will be. This is especially important when scheduling between people
in multiple timezones.
The right way to handle this is to store the intended local time + a location
such as America/Toronto
. EST
is not enough, because it’s EDT
half the
year, and obviously neither is -0500
. I grew up in the netherlands, and it
was only when I got into programming I realized that our timezone is not
+0100
all year round, unlike what we learned in school.
Timezones are relatively stable in North America, but the US also made a
change in 2007, and it sounds like we may have another one in the future!
So this bi-annual time change was a great reminder to many developers that
timezones are a thing, and you can’t just naively assume a UTC time + an
offset is enough. Even more so for teams that are spread cross-continent
because the DST change doesn’t fall on the same day. Currently I’m in the
3 weeks per year the time difference between me and my parents is 5 instead of 6 hours.
A lot of programming is (seems?) anglo-centric. A similar situation is that
before Emoji became wide-spread it was way more common to see a lot more
issues around encoding non-ascii characters (billpg). Especially in
languages that don’t have good native unicode support (looking at you PHP).
So if DST goes away in North America, I predict we’ll see more people assuming
using the offset is enough, resulting in bugs related to:
- Times in countries that have not yet abolished DST.
- Countries that ever change timezone rules. (This happens more often than
you think!) - Applications that deal with historical data.
It doesn’t help that one of the most common date formats (ISO 8601) uses an
offset! (2022-03-18T17:05:30.996-0400
). This is OKish for things that have
already happened, but not good for anything in the future.
So when you hear developers excited about the US abolishing DST because it
will make their (work) life simpler, remind them this is only true if you
never intend your software to be used outside of North America, or when the
entire rest of the world makes the same change and also freezes all
timezone rules forever!
Too much magic? – Matthias Noback
Years ago my co-worker Maurits introduced me to the term “magic” in programming. He also provided the valuable dichotomy of convention and configuration (or in fact, he’d choose configuration over convention…). I think this distinction could be very helpful in psychological research, figuring out why some people prefer framework X over framework Y. One requires the developer to spell out everything they want in elaborate configuration files, the other relies on convention: placing certain files with certain names and certain methods in certain places will make everything work “magically”.
And there we are: magic. Often used in code reviews and discussions: “there’s too much magic here”. Yesterday the word popped up in a Twitter thread as well:
“symfony has too much magic, to its own detriment…” @bazinder
This was answered with:
“I’d say that everything is magic until you start to understand it :D” @iosifch
It made me wonder, what should we consider to be “magic” in programming? Is magic in code okay, or should it be avoided at all cost?
As an example of magic, the fact that you can define a controller like this, is already magical:
/** * @Route("/task") */
final class TaskController
{ /** * @Route("/new") */ public function new(Request $request): Response { // ... }
}
Who invokes it? Why, and when? You can’t figure that out by clicking “Find usages…” in PhpStorm!
This innocent example shows how quick we are to accept magic from a framework. Just do things “the framework way”, put this file there, add these annotations, and it’ll work. As an alternative, we could set up an HTTP kernel that doesn’t need any magic. For instance, we could write the dispatching logic ourselves:
$routes = [ '#^/task/new$#' => function (Request $request): Response { $controller = new TaskController(); return $controller->new($request); }, // ...
]; foreach ($routes as $path => $dispatch) { if (/* request URI matches path regex */) { $response = $dispatch($request); // Render $response to the client exit(); }
} // Show 404 page
Of course we wouldn’t or shouldn’t do this, but if we did, at least we’d be able to pinpoint the place where the controller is invoked, and we’d be able to inject the right dependencies as constructor arguments, or pass additional method arguments. Of course, a framework saves us from writing all these lines. It takes over the instantiation logic for the controller, and analyzes annotations to build up something similar to that $routes
array. It allows other services to do work before the controller is invoked, or to post-process the Response
object before it’s rendered to the client.
The more a framework is going to do before or after the controller is invoked, the more magical the framework will be. That’s because of all the dynamic programming that’s involved when you make things generic. E.g. you can add your own event subscribers that modify the Request
or Response
, or even by-pass the controller completely. It’s unclear if and when such an event subscriber will be invoked, because it happens in a dynamic way, by looping over a list of event subscriber services. If you have ever step-debugged your way from index.php
to the controller, you know that you’ll encounter a lot of abstract code, that is hard to relate to. It’s even hard to figure what exactly happens there.
I’m afraid there’s no way around magic. If you want to use a framework, then you import magic into your project. Circling back to Iosif’s comment (“everything is magic until you start to understand it”), I agree that the way to deal with your framework’s magic is to understand it, know how everything works under the hood. It doesn’t make the magic go away, but at least you know how the trick works. Personally I don’t think this justifies relying on all the magic a framework has to offer. I think developers should need as little information as possible to go ahead and change any piece of code. If they want to learn more about it,
- They should be able to “click” on method calls, to zoom in on what happens behind the call.
- They should be able to click on “Find usages” to zoom out and figure out how and where a method is used.
When you get to the magical part of your code base, usually the part that integrates with the framework or the ORM, then none of this is possible. You can’t click on anything,
Truncated by Planet PHP, read more at the original (another 3806 bytes)
Concerning Cassini – Derick Rethans
Concerning Cassini
At the beginning of the year, I saw a tweet by my friend Ben Ramsey, where he quoted Carolyn Porco’s tweet requesting help saving CICLOPS, the web site of the Cassini Imaging Central Laboratory for Operations, which was under threat of disappearing off the internet.
I have been enthusiastic about space since I was in my early teens, with at some point expressing the interest to be an astronaut. I never pursued that, but I have continued to express great interest in space exploration.

I have dabbled in some astrophotography, having some mediocre successes with last year’s comet NEOWISE. I never got into the field of astronomy nor photography. Instead I started doing web technology, including PHP, which how I know Ben.
Tech is cool too, but I always hoped to do something for, and with, space exploration.
So when I saw Ben’s tweet, I thought this would be something I could help with, so I reached out to Carolyn via DM.
The task at hand at that time seemed to create a static copy of the existing CICLOPS website, but after some twitter to-and-fro, an additional ask seemed to be to create a functionally equivalent static search.
Over night, Ben had mirrored the CICLOPS website with wget
and I took his copy to make some improvements, and started doing some research into how to do a static search. I had quite some experience with SOLR as well as full text search in general and with MongoDB. The problem was that all of these needed something to run on, which would create complications and costs, beyond just hosting a static site on something like S3.
After some research through DuckDuckGo, I found a neat JavaScript library, called Lunr, which looked perfect for a quick-and-dirty static search engine. Like most other more complex search engines, Lunr creates a reverse index that maps every word back to a location in a document, with some clever maths to rank more specific words higher in the results.
I started writing a script to extract the text from the crawled CICLOPS site to pick out the actual descriptions of each post and media item, and then made that index into Lunr’s full text search index. With that, I set up a static site on S3 as a demo. This demo could have become a crude final result, and would have saved all the original content and images of the Cassini space probe.
That was the easy part.
In the course of several weeks, I worked with Ben, Carolyn, Jakub and David to refine the search index, split it into several different categories (the one with the images is my favourite!), added pagination, phrase searching, and a ton of other tweaks to make the static CICLOPS site an excellent simile of the original dynamic site, which turned out to be written in PHP!
To be honest, this took a lot more work than I originally had thought, with many hours spend on my side, all in the name of science.

The resulting site is something to be proud of. The search is faster and more capable: look at the instructions! I finally managed to do something space related—and that all for my favourite planet!
I would explore you to have a search through the rich set of images that is available on the CICLOPS site, and let me know what’s your favourite!