PHP Annotated — May 2021

Greetings everyone!

PHP 8.0 is gaining momentum and adoption is increasing, as evidenced by Composer’s statistics.

Meanwhile, PHP internals have accepted a bunch of changes for PHP 8.1, including a new never type and namespaces in bundled PHP extensions, and some features that will be deprecated.

The PHP 8.1 release managers have been selected, and there are several interesting proposals under discussion, including property accessors, pure intersection types, and final constants.

Read more about this news in the May edition of PHP Annotated. As usual, we’ve carefully selected a collection of articles, tools, videos, and streams for you.


PHP Versions Stats – 2021.1

The traditional compilation of statistics based on the data that Composer sends when it connects to

PHP 7.4: 45.92% (+3.31)
PHP 7.3: 21.30% (-5.75)
PHP 7.2: 12.89% (-2.39)
PHP 8.0: 9.44% (+9.17)
PHP 7.1: 5.21% (-2.24)

PHP is available on Google Cloud Functions

Google Cloud’s serverless platform now natively supports PHP. With GoogleCloudPlatform/functions-framework-php/ you can run functions in a PHP 7.4-based runtime.

There are a few more details in the discussion on GitHub in the Symfony repository. Symfony 5.3 should run on GCF smoothly, thanks to the Runtime component. You just need to install php-runtime/google-cloud.

Composer Command Injection Vulnerability

The vulnerability in Composer only affects systems that have Mercurial installed. However, it is worth immediately updating to versions 2.0.13 and 1.10.22, which contain fixes. Check out a more detailed technical analysis of the vulnerability.

Follow up on attack

Attackers pushed two commits to the PHP source on behalf of Rasmus Lerdorf and Nikita Popov. The problem was quickly detected and solved. The malicious code did not get to users.

As it turned out, the server allowed commits via HTTPS and used digest authentication, which accepts md5 hash as a secret. The hash database of all the contributors was obtained by the attackers from, which was probably the server that was originally compromised.

As a result, all development has been fully moved to GitHub, which makes life easier for language developers.

PHP 7.4.19, PHP 8.0.6 – With a fix in PDO_pgsql.

PHP Internals

[RFC] never type

PHP 8.1 will have a new type for returned values: never.

A function or method declared with the never type indicates that it will never return a value, and it either throws an exception or terminates with a call of type die(), exit(), trigger_error().

It is an empty bottom type and is a subtype of all other types, and there are similar types in Python, Rust, Kotlin, and TypeScript. This type improves static analysis.

function redirect(string $uri): noreturn {
header(‚Location: ‚ . $uri);

function redirectToLoginPage(): noreturn {
You can find more details on PHP.Watch or listen to the PHP Internals News podcast with Matt Brown and Ondřej Mirtes.

[RFC] Deprecate implicit non-integer-compatible float to int conversions

In PHP 8.1, an E_DEPRECATED notice will be thrown when float is converted into int and fractional part is lost. Later, in PHP 9.0, this will cause a TypeError.

function acceptInt(int $i) {

> int(3) // Deprecation notice
Learn more from the PHP Internals News podcast #83 with George Peter Banyard.

[RFC] Phasing out Serializable

In PHP 8.1 the Serializable interface will be deprecated. A deprecation notice will be thrown when the class uses only this interface, that is, if the class does not additionally have the new magic methods __serialize() and __unserialize().

[RFC] Namespaces in bundled PHP extensions

This marks a small step towards cleaner PHP! New symbols (classes, interfaces, etc.) in extensions will now have to use namespaces.

Here’s an example. The resource type is de-facto obsolete in PHP, and all existing resources are slowly being migrated to objects. In PHP 8.1 some resources will be replaced with the following namespaced classes:

IMAPConnection -> IMAPConnection
FTPConnection -> FTPConnection
LDAP -> LDAPConnection
LDAPResult -> LDAPResult
LDAPResultEntry -> LDAPResultEntry
PgSql -> PgSqlConnection
PgSqlResult -> PgSqlResult
PgSqlLob -> PgSqlLob

[RFC] Add return type declarations for internal methods

Most of the built-in methods in PHP 8.0 have received parameters and return type declarations. In some cases, however, this could not be done, like for the return values of public non-final methods. The problem is that they can be overridden in user code.

Here is an example to illustrate the problem

class SomeStandardClass
public function method(): int {}

class UserClass extends SomeStandardClass
public function method() {}

// Fatal error: Declaration of UserClass::method() must be compatible with SomeStandardClass::method()

There will now be a gradual migration for such cases. In PHP 8.1, all internal methods will also get the missing types. If they are overridden in user code, a Deprecation notice will be thrown.

class MyDateTime extends DateTime
public function modify(string $modifier) { return false; }

// Deprecated: Declaration of MyDateTime::modify(string $modifier) should be compatible with DateTime::modify(string $modifier): DateTime|false

Release managers for PHP 8.1 have been selected

There will be three managers this time around: the experienced Joe Watkins (pthreads, parallel, pcov), and two newcomers, Patrick Allaert ( and Ben Ramsey (ramsey/uuid). Check PHP Internals News podcast #84 with Ben and Patrick.

New proposals for PHP 8.1:

[RFC] Partial Function Application

Partial function application (partial functions) is when only some arguments are bound on function call, and the others remain as parameters to be passed later.

For example, here is a full function:

function whole($one, $two) {
/* … */
And here’s a partial one based on it:
$partial = whole(?, 2);
In this case, the partial signature will look like this:
function($one) {
/* … */
Why is this needed?

Firstly, you can now get a reference to any function or method and pass it wherever Callable is expected. For example, you could do this

array_map(Something::toString(?), [1, 2, 3]);
array_map(strval(?), [1, 2, 3]);

// instead of
array_map([Something::class, ‚toString‘], [1, 2, 3])
array_map(’strval‘, [1, 2, 3]);
And secondly, as a consequence, it will be possible to implement the pipe operator |>:
$result = „Hello World“
|> htmlentities(?)
|> explode(?);
See it in action at

Thanks to Larry Garfield, Joe Watkins, Levi Morrison, and Paul Crovella for the RFC and the implementation.

[RFC] Property Accessors

Nikita has finalized the implementation of the property accessors, and the proposal is now officially under discussion.

The bottom line is that traditional getters and setters are not convenient to use, and the magic methods __get and __set are not specific. The new accessors are meant to fix these issues.

The syntax is inspired by C#:

class Foo {
public $prop {
get { /* … */ }
set { /* … */ }

You can use them to implement read-only properties:
class User {
public string $name { get; }

public function __construct(string $name) {
$this->name = $name;

And you can specify asymmetric access, i.e. make them public or private separately for reading and writing:
class User {
public string $name { get; private set; }


Or you can use them as full-fledged methods for validation or other actions:
class Foo {
public int $bar {
get {
error_log(‚Getting $bar‘);
return $this->bar;
set {
assert($bar > 42);
$this->bar = $bar;

[RFC] Pure intersection types

Union types were added in PHP 8.0, and this RFC proposes to add intersection types.

The syntax is TypeA&TypeB, and it means that the variable must be both instanceof TypeA and instanceof TypeB.


class A {
private Traversable&Countable $countableIterator;

public function setIterator(Traversable&Countable $countableIterator): void {
$this->countableIterator = $countableIterator;

public function getIterator(): Traversable&Countable {
return $this->countableIterator;

The proposal is called “pure intersection types” because combinations with union types are not supported and are being left for future consideration. Aliases for complex types are also being left for the future.

[RFC] Deprecate ticks

There is a tick mechanism in PHP: declare(ticks=1). It was originally needed to track pcntl signals. Now you can use pcntl_signal() and pcntl_async_signals() for this, which is why there’s been a suggestion to deprecate ticks in PHP 8.1 and remove them completely in PHP 9.

[RFC] Final class constants

The author of this RFC proposes a final modifier for constants, so that they cannot be overridden in child classes.


class Foo
final public const X = „foo“;

class Bar extends Foo
public const X = „bar“;

// Fatal error: Bar::X cannot override final constant Foo::X

Fun fact from RFC: constants in interfaces are already final.

A couple more links for those who would like to start contributing to PHP source:

Using CLion with php-src – Instructions from Ben Ramsey, one of the release managers for PHP 8.1.
How to compile PHP from source on Debian/Ubuntu – Beginner’s guide on PHP.Watch.


spatie/data-transfer-object v3 – Advanced typed data transfer objects for PHP 8.
spatie/fork – A wrapper for pcntl_fork to simply and conveniently run PHP scripts in parallel. Learn more in this blog post and this video overview.
phpbench/phpbench 1.0.0 – A useful tool for benchmarking your code. The new version has a lot of updates, including PHP 8 support. Learn more in Release Radar #10 with Dan Leech.
rybakit/phpunit-extras – Custom annotations and expect*() methods for PHPUnit to make tests cleaner.
infection 0.23.0 – Mutation testing tool update, now with support for pestphp/pest.
captainhookphp/captainhook – Git hooks management for PHP projects. For example, you can easily set up a style check or run tests before pushing to the repository.
0xABADCAFE/php-demo-engine – A demoscene engine in PHP that was just made for fun. Displays graphics with ASCII symbols in the console.


What’s coming in Symfony 5.3
End-to-end testing with Symfony and Panther.
Batching Symfony Messenger messages using pcntl_alarm().
PrestoPHP/PrestoPHP – The Silex microframework is deprecated and has not been supported for quite some time, but this maintained fork is to the rescue.
A week of Symfony #750 (10-16 May 2021)


laravel/octane 1.0 – This package allows you to run Laravel under Swoole or RoadRunner, with the bootstrap executed once and then each request handled by the same application instance. Learn more about changes for application developers in Mohamed Said’s post, and also from Marcel Pociot.
thedevdojo/wave – A skeleton for creating a SaaS with Laravel. It has user profiles, subscriptions, an API, admin, and a blog out of the box.
laravel-arcanist/arcanist – A package for building multi-step form wizards. Check out this a detailed overview from Kai Sassnowski.
cerbero90/lazy-json – A package for loading heavy JSON in lazy collections from illuminate/support.
mailcare/mailcare – A disposable email address service like built on Laravel.
Event Sourcing in Laravel – A paid course from the folks at Spatie. Part of it is available for free.
How Christoph Rumpel tests Livewire components.
Laravel Worldwide Meetup #8


Yii news 2021, issue 2 – News about Yii 3 and a set of Yii 2 releases, as well as interesting projects not directly related to code.
New packages for Yii 3: yiisoft/profiler, yiisoft/error-handler, yiisoft/translator, yiisoft/yii-event, yiisoft/assets.


Using PhpStorm’s Live Templates for Doctrine fields.
A quick way to browse Symfony logs in PhpStorm with Ideolog.
Fully integrate DDEV and PhpStorm including Unit Tests with Coverage.


Upgrading a Project to PHP 8.0 — A plan for the update and an account of the key potential difficulties when upgrading the codebase to 8.0.
Do not mock what you do not own – Because if you don’t control the replaced dependencies, things can quickly get out of control.
Named-entity recognition in PHP – An example of solving a simple ML problem using RubixML.
Using exceptions and retries when working with network services.
Algorithmic complexity (big O notation) of built-in PHP functions.
A look into the most popular packages on Packagist and their licences – Many popular packages either do not have a license or have it set up incorrectly.


Modern PHP with Rasmus Lerdorf – The father of PHP talks a little bit about Etsy code and PHP 8.
Videos from Derick Rethans on Xdebug 3: Xdebug with Docker and PhpStorm in 5 minutes, Profiling with Xdebug in Docker, Debugging Unit Tests with PhpStorm on Linux.


PHP Ugly podcast:
#236: – Memory Leaks.
#235: – Ugly Hot Tub PHP Coding.
PHP Release Radar:
Episode #9 – With Andreas Braun discussing Doctrine Cache 2.0.
PHP Internals News podcast:
Episode #82 – About auto-capturing multi-statement closures (RFC) with Larry Garfield and Nuno Maduro.
Episode #79 – About the new operator in initializers with Nikita Popov.


PHP’s bus factor is 2 – Joe Watkins says that only two people know enough about the PHP source, so we should consider this when thinking about adding new features to PHP. He also says that we need more developers working on the core.

Thanks for reading!

If you have any interesting or useful links to share via PHP Annotated, please leave a comment on this post or send me a tweet.

Subscribe to PHP Annotated

Your JetBrains PhpStorm team
The Drive to Develop

The PhpStorm Blog : The Lightning-Smart IDE for PHP Programming | JetBrains Blog
Read More

Latest News


PHP 8.0.19 released!

PHP 7.4.29 released!