DEV Community

Len Woodward
Len Woodward

Posted on • Originally published at youtu.be

This Week In PHP Internals | July 1, 2026

Hello world, it's Canada Day 2026, and here's what happened This Week in PHP Internals.

This week's episode is supported by OurCVEs. Hundreds of CVEs ship every week, and almost none of them are about you — until one is. OurCVEs inventories your entire infrastructure and only surfaces the security risks that actually apply to your team. Free for open source at ourcves.com.

This week's top story is still Gina P. Banyard's Deprecations for PHP 8.6 — the once-a-year housekeeping RFC that gathers a stack of unrelated removals under one roof, where each one stands or falls on its own separate vote. With 8.6's first alpha getting built this very week, the clock is loud. But the fight this week wasn't about any single removal — it was about evidence: does every deprecation owe voters an impact analysis? Tim Düsterhus argued no, at least not as an unconditional rule — a deprecation has years of runway, and a survey of existing code can't measure the upside of a cleanup.

Juliette Reinders Folmer had offered to build those impact analyses, and her exchange with Tim turned personal — an accusation of gaslighting, which Tim rejected. But she was far from alone on the substance. Rowan Tommins came to her defense, and he didn't warm up first. Rowan wrote: "I hate this argument." His point: deprecating something is really a proposal to remove it later, so the impact of that removal is exactly what voters deserve to see — and to leave it out to protect your case, he said, would be dishonest. Larry Garfield backed the same call: put the impact on the table, or read the angry blog posts come December.

And this particular RFC kept growing right up against the freeze. Seifeddine Gmati proposed deprecating list(), and got the room's attention: Ayesh Karunaratne clocked "7 million hits" for list( on GitHub and called the break too big; Rowan noted you can't really retire list() while array() stays — to which Seif said, fine, then maybe deprecate array() too. Nick moved to reserve namespace as a constant name. Ilia Alshanetsky floated finally sunsetting open_basedir — Derick Rethans said "Yes, but for PHP 9," while Jakub Zelenka was firmly against it. Add a careful fight over how narrowly to kill the dechunk filter, plus Tim's pitch to retire gettype() for get_debug_type(), and that's a lot of small knives being sharpened at once.

Carrying over: Tim and Derick's Time\Duration class — the immutable stopwatch value that's meant to be the first brick of a modern date-and-time API. One line of context, then this week's moves: they're dropping the word "period" from the method names (Derick pointed out ISO itself walked away from it); they're lifting the ban on negative durations after Paweł Kraśnicki showed up with a real use case; and the whole thing may slim down for 8.6 — ship addition, subtraction and multiplication now, and let dividing one duration by another wait. Ignace Nyamagana Butera and Nick are already bikeshedding whether that division should hand you back a tuple or a tidy little value object.

The single busiest thread of the week was brand new: Rob Landers formally opened Primary Constructors — the whole constructor hoisted up onto the class line itself. His numbers are the pitch: something like 30 to 40 percent of all constructors are completely empty, and by his count 71 percent of Laravel and 61 percent of Symfony classes could use this. The catch is deliberate — a class with a primary constructor can't also declare a regular __construct, and it can't carry a body.

That no-body rule is the whole fight. Nick pushed for a body — mostly so readonly classes have a way through — and warned this could ship as yet another half-a-feature. But Rob held the line. He wrote: "If you need a body, use a constructor -- that's what they're for." Rowan and Tim are with Rob — Tim called the limitation "a feature," and put it simply: "[To] reduce typing alone is not a sufficiently strong argument in favor of a new feature." Seifeddine went further: "Personally, I really dislike this feature." His read — primary constructors don't remove repetition, they just relocate it. Larry, meanwhile, wants a Kotlin-style init block bolted on. Plenty's still unresolved — visibility, attributes, anonymous classes — so we'll be keeping an eye on this one.

Newcomer Michal Kral floated a spicy pre-RFC: methods on scalars. Write (3)->pow(2), or " hello "->trim()->upper(), with the call rewritten at compile time into a hidden helper — but only when the compiler can already prove the value is a scalar. He was upfront that he built it with an AI assistant. The reception was cool: Seifeddine's core objection is that PHP compiles one file at a time, so "the compiler already knows it's a scalar" covers almost no real code — the same line would work or fail depending on what's autoloaded. His fix, nicely put: "Solve the naming problem with naming, not by blinding the tooling." And Rob warned the whole thing leans on casts, which in PHP are dangerous(int) of the string "123password" is just 123.

Alex Pătrănescu opened a pre-RFC for runtime modules — a way to give each package its own private symbol table so two versions of the same library can finally coexist in one request. Rowan Tommins spent the week reframing it as containers — a boundary you run other people's code inside, Docker-style — and kept circling the genuinely hard part: what happens when an object crosses the wall between two containers? A second contributor, Alexander Egorov, pitched version "tags" instead; Rowan's worry is that tags leak the container's insides right back out. No code yet — but a problem the whole ecosystem feels.

The rawest thread of the week came from a user, not an internals regular. Michael Morris wrote what he openly called a "Disheartening Rant" after Edmond Dantes said his own TrueAsync RFC has, in his words, a 90 percent chance of not being accepted. Morris didn't hold back: "If you want PHP to be the next COBOL, this is how you go about it." His killer example is WebSockets — the thing PHP still can't really do on its own. Ilia Alshanetsky pushed back gently (he's actually written COBOL, and reports it isn't dead): async matters, but its reach in a request-based language is narrower than it looks.

Larry Garfield drew the line that matters — the same one that just sank generics. Larry wrote: "Don't confuse 'this is not the async we're looking for, done in a painful process' with 'we don't want async at all, ever.' The first is what happened. The second is simply untrue." His critique isn't of async — it's of how TrueAsync arrived: enormous, one author, hundreds of far-reaching decisions, feedback taken selectively. His fix is a real working group to design it together. Nobody's against the destination — they're against the map.

To the ballots — and this was a brutal fortnight for the marquee names. Seifeddine's Bound-Erased Generics closed and was declined: 7 in favour, 19 against, 10 abstaining — nowhere near the two-thirds. And Nicolas Grekas's __exists() magic method went down with it, 2 to 13. The two features that would've made the headlines both missed.

But look what did pass — the quiet, careful stuff, every one without a single No. Tim's deprecation of returning values from __construct and __destruct: accepted unanimously, 39 to nothing. Sjoerd Langkemper's cap on php://filter chains — that local-file-inclusion-to-RCE fix — accepted 30 to nothing, 2 abstaining. And Weilin Du's Locale display-keyword additions: in, 18 to nothing, 2 abstaining. And one's still live on the board — Jordi Kroon's move to lift third-party extension docs out of the manual is out in front at 25 to 1, one abstaining, with the vote closing July 3; on the side questions the room is leaning toward a php.net subpath over a separate subdomain, 14 to 8, and toward dropping the old user notes rather than migrating them, 20 to 4. The pattern's getting hard to miss: the bold swings keep getting sent back, while the tidy, well-scoped changes keep sailing home.

Quick hits. That newcomer arc — Sepehr Mahmoudi's grapheme_mask — got RFC karma and a warm discussion, then tried to call a vote for July 3 and was told, kindly, it's not ready: no discussion link, freeze period not met, window too short — the process catching a first-timer before the fall. Khaled Alam's write-to-constants RFC grew to cover class constants, so its vote slipped. Gianfrancesco Aurecchia's DTLS idea converged fast — Jakub steered it from a new class to a simple dtls:// stream, maybe no RFC needed at all. Gina volunteered to review the long-stranded snmp extension work. Seifeddine's Literal Scalar Types reached version 0.3. Jorg Sowa's case-sensitive-PHP revival was withdrawn. And PHP 8.6.0 alpha 1 got built — which is why everyone's sprinting.

So that's the week: a deprecations RFC that turned into a fight about honesty, a stopwatch class quietly going on a diet, a brand-new primary-constructors debate, a heartfelt plea for async — and the two flagship votes falling while the small ones walked right in. Links to every thread are below. We're Artisan Build. See you next week.

Top comments (0)