Four out of five, and the language still matters

On this page

Sebastian Bergmann, the person behind PHPUnit, wrote a piece called Four out of five. It is the most useful thing I have read about PHP this year, and it is not a defence of PHP. He says so up front: defences accept the frame that PHP has to justify itself against what people remember from PHP 4, and that genre is done.

Instead he borrows a checklist. Rhombus, a new language built on Racket, opens its goal statement by naming what modern languages broadly agree on: lexically scoped variables and closures, objects, pattern matching, and type parametricity. Then he asks how PHP in 2026 measures up.

The scorecard

Closures: yes. Lexically scoped, with explicit capture. function () use ($x) names exactly what crosses the boundary. PHP 8.5 added the pipe operator, and 8.6, due this November, adds partial function application. Together that is real function composition.

Objects: yes, and then some. Enums, readonly properties, property hooks, asymmetric visibility, clone with. A modern PHP class says what is immutable, what is computed and what may be overridden, and the engine checks it at runtime.

Pattern matching: half a point. match has been strict since 8.0, but it matches values, not shapes. A Pattern Matching RFC with a working implementation is on the table, and he expects it in 8.7 next year.

Generics: no, on purpose. This is the best part of the article. A proposal for erased generics was declined for 8.6, and not because nobody wants generics. Every type declaration PHP has ever gained is checked at runtime. Syntax that looks like a type but is silently not enforced would break that promise, and most people seeing it would assume it is enforced. Java and TypeScript get away with erasure because they have a mandatory compile step. PHP doesn't.

Meanwhile, real codebases already use generics through docblocks: list<Order>, array<string, Money>, checked by PHPStan, Psalm and PhpStorm. He calls that PHP's accidental extensibility: a full type language layered on top, moving at tooling speed instead of language speed, and honest about not making runtime claims.

The one missing from the list: concurrency. Matt Brown pointed out that the checklist skips it, and Bergmann agrees it is where PHP is furthest behind. Fibers have existed since 8.1, but PDO and mysqli still block, so coroutines do little for a normal app that mostly waits on a database. There is an RFC for an engine scheduler aimed at 8.7, and non-blocking I/O is still future work.

His conclusion: a 31-year-old language that adopted most of the consensus, found an odd but working answer to extensibility, and never lost track of its domain. Shared-nothing, request-scoped execution is still the floor, not something you assemble from frameworks.

Why I've been hiding in PHP

I'll be honest about my angle. The last year has been rough in this field, and I have been leaning into PHP as a comfort. Not nostalgia. Comfort in the sense of solid ground.

It ships a release every November. It deprecates things one voted RFC at a time. Each request starts clean and ends in oblivion. When something breaks at 2am, I know where to look. That kind of predictability is worth a lot when everything around the job feels like it is being rewritten every quarter.

"Languages don't matter anymore"

There is a claim going around that languages no longer matter because AI writes the code. Pick whatever stack, the model will handle it.

It sounds clever until you are the one being paid.

As a professional, I don't get paid for producing a diff. I get paid for what ships and for being accountable when it breaks. The diff has become cheap. Understanding the problem hasn't.

Understanding is language-specific. Reviewing generated code means knowing what use ($x) captures and what an arrow function captures instead. It means knowing that a native type is checked at runtime and a docblock type isn't. It means knowing that the JSON coming in from an API is untyped until something checks it, and that a single blocking call stalls the whole worker. The model can type all of that. It can't be responsible for it. I am.

Read his generics section again with AI in mind. PHP refused to add syntax that looks like a guarantee but isn't one. That is exactly the property you want when more of the code is written by something that cannot be held accountable: fewer things that look safe and aren't. Constraints that the runtime actually checks are more valuable now, not less.

And the market hasn't heard the news either. Job ads still ask for years in a specific stack. Teams still have a Laravel codebase or a WordPress platform or a Symfony monolith, with a decade of decisions baked in. Nobody is hiring "can prompt in any language". They are hiring someone who can own that codebase.

So no, languages have not stopped mattering. What changed is where they matter. Less in typing the code out, more in reading it, judging it and standing behind it. Depth in one language is how you do that well.

Four out of five is fine

I don't need PHP to be the best language. I need it to be one I know down to its edges, that keeps getting better on a schedule I can plan around, and that fits the work people actually pay for. Four out of five, with the gaps named honestly and work underway on them. I'll take it.

I wrote about PHP in 2024 too. It has moved a lot since.


Read the original: Sebastian Bergmann, Four out of five, phpunit.expert