❌

Reading view

This Week In PHP Internals | Oct 29, 2026

Preface: what follows is the word-for-word transcript of the spoken dialogue in the video, chapter by chapter with timestamps, for anyone who'd rather read than click through. If this digest is still too long for you, we recommend copying it into your LLM of choice and asking for a summary of our summary.

Cold Open (00:00)

A week after two critical bugs in PHP's own engine, someone asked the internals list to stop. No new features and no cosmetic deprecations, until PHP has a formal spec and four independent implementations, written in formal-methods frameworks. Four people who work on PHP replied. One of them called fixing PHP's bugs a money problem.

Hello world, it's Thursday, October 29, 2026, and here's what happened This Week in PHP Internals. 15 stories this week, so let's get into it. But first,

AI made building software easy, and owning it hard. Scalpels installs open source apps into your own Laravel Cloud or Forge account in one click, so your data never leaves your infrastructure. There are 15 apps in the catalog, from a private Composer registry to a mail trap for staging. The Free plan is zero dollars, forever, and Laravel bills you directly for the hosting. There's even a guide to patching PHP on your own servers. Scalpels launches this Saturday, October 31st, at scalpels.app.

Spec Debate (01:21)

This week's top story: after last week's emergency releases, Brian Nguyen argued that PHP's two critical bugs show the cost of having no formal specification and only one implementation. He proposed a living spec of the bytecode and the parser, executable semantics in research frameworks like K and PLT Redex, and testing any second runtime against WordPress, Laravel and Symfony. His first mail said it was not an embargo. The next morning, he opened a second thread asking for one, until four formal implementations exist. He wrote: "Not adding a feature cannot break apps. Not deprecating (integer) cannot break apps. A corrupt allocator can."

Rowan Tommins doubted a spec would have helped, since memory management is exactly what differs between implementations. And on .NET, he pointed out that if 0.01% of Microsoft's roughly 200,000 employees work on it full time, that's still twice as many as have ever been paid to work full time on PHP. Sjoerd Langkemper wrote: "I think PHP is not starved for bugs. The bottleneck is bugfixes." And Larry Garfield wrote: "This is a money problem, just like most major OSS projects. It's nothing more complicated than that."

His fix is to get PHP-using companies to become significant PHP Foundation sponsors, or to put their own employees on PHP full time. Ben Ramsey asked whether Brian wanted PHP's maintainers to stop building PHP. Other runtimes were built by their communities, he wrote, and companies with the resources should be doing that work. Brian hasn't replied yet.

Links: Brian Nguyen, "From mono-implementation risk to spec" · Larry Garfield, "This is a money problem"

Security Follow-ups (03:02)

If you run PHP on Windows, there's one more update to install. On Monday, Shivam Mathur announced rebuilt Windows packages for PHP 8.2 through 8.5, with Brotli 1.2.1. That fixes a critical out-of-bounds write in the Brotli decoder, rated 9.2, which PHP can reach through the curl extension when automatic response decompression is on. It's off by default in curl, but HTTP client libraries can turn it on. The PHP versions don't change, and the dash-1 marks the rebuilt package.

And on Friday, php.net posted an informational advisory: "We suggest you set session.upload_progress.enabled=0 until the next regular bugfix release, to fully protect from an unlikely RCE vector." It needs an unusual combination of configuration and application code, so the full advisory, for a new CVE, comes with the next release. If you applied that setting as a mitigation last week, keep it in place.

Links: Updated PHP Windows builds for the Brotli fix · Informational advisory: session upload progress

Newcomer PRs (04:07)

About half of the pull requests from first-time contributors to php-src have been accepted, and the first success matters most. Artem Ukrainskiy went through a year of data: 831 pull requests from 219 people who opened their first one in that time. 418 were accepted, 157 closed without a merge, and the rest have no outcome yet. A first PR was accepted 29% of the time, and after a first acceptance, 66%. PRs with AI-written descriptions were accepted around 20% of the time, against 55%.

And speed matters. When a maintainer responds within a day, the median PR closes in about 20 hours. When the first response takes over a week, it's about 32 days. So he asked whether a bot is worth prototyping, one that checks the mechanical things as soon as a PR opens: missing tests, an empty description, the wrong target branch, an obvious duplicate.

Sjoerd Langkemper replied that his biggest friction as a newish contributor was opening a pull request and having nobody respond. Artem's question started from a new rule by Weilin Du, merged Saturday, that asks contributors, and AI agents, to review an existing fix instead of opening a duplicate. No maintainer has answered the bot question yet.

Links: Artem Ukrainskiy, "What happens to newcomers' PRs in php-src"

Scope RFC (05:30)

PHP has no object that represents a request, because until now a request has been one run of the engine, from startup to shutdown. That breaks down when one process serves many requests at once, and Frode Børli's Scope RFC gives each unit of work an identity: an HTTP request, a queue job, a CLI command. Code anywhere in that request can ask which scope it's in, and keep its own state, like a database connection, keyed by it.

Fibers and generators belong to the scope they were created in. The primary vote adds only that identity. Two secondary votes would make the superglobals and the session, and then the default locale and timezone, follow the scope. Code that never creates a scope behaves exactly as today, and there's already an extension and a polyfill.

Larry Garfield called it promising and tightly focused, but asked what it looks like with real dependency injection, rather than a service locator. He also called new scopes with empty superglobals a footgun for legacy code that reads $_POST. Frode replied that the server fills them when it creates the request scope, the same place that fills them today, and that he'll swap the examples for a container.

Links: RFC: Scope

Effect Declarations (06:46)

What if a function had to declare that it starts processes, reads files or makes network requests? Arsan Gamal proposed effect declarations, written after the return type, with optional parameters that narrow them, like the one command this function may run. A separate runtime mechanism would decide what's actually allowed. He named PHP2Shell, the finders' name for last week's vulnerabilities, as the motivation, and compared it to app permissions on a phone. He wrote: "My intention is not to promote process execution, but to make potentially dangerous operations explicit and controllable."

David Maye liked it, noted that a use-after-free couldn't be contained this way, and suggested prototyping it as an extension with attributes. Damian Jóźwiak asked the same thing: why new syntax instead of attributes? Larry Garfield replied that attributes work for static analysis, but for the engine to enforce it, backward compatibility is the problem. He wrote: "A new PHP release that fails on any function that has a print or fopen statement in it until you add new syntax not available in earlier versions is a complete non-starter." So his first question is how to make it piecemeal opt-in. Calvin Buckley added that these aren't algebraic effects, and suggested a name other than effects or capabilities.

Links: Arsan Gamal's proposal

Array Partition (08:12)

Splitting an array into the items that pass a check and the ones that don't takes two passes today, one of them negated. Ayoub Ezzini's RFC adds array_partition, which returns both halves in one pass, matching first, with keys preserved, so you can destructure straight into two variables.

mickmackusa asked for any number of groups, keyed by the callback's result, and Morgan for a result keyed true and false. Ayoub kept it to two. Partition means a two-way split in Ruby, Kotlin, Rust, Haskell and Laravel, he wrote, and PHP casts boolean array keys to 1 and 0, so a true-and-false result would quietly swap your variables.

Tim Düsterhus said a co-worker hand-wrote his own array_partition just last week, and wrote: "It's a well-written, well-researched and well-argued RFC and I'm in favor of the proposal." Writing the polyfill Tim asked for turned up the open question: whether array_partition keeps references, like array_filter, or drops them, like array_find.

Links: RFC: array_partition()

Votes (09:22)

Two votes are open, heading in opposite directions. Sjoerd Langkemper's RFC to make hexdec, octdec, bindec and base_convert throw on invalid characters is at 25 to 1, and it closes November 1st. Muhammed Arshid's Filter enums RFC is at 2 to 11, with 1 abstention, and it closes November 4th.

Links: Throw exception for invalid characters in number base functions · Add Filter\Filter and Filter\Flag Enums

Quick Hits (09:44)

Quick hits. Sjoerd Langkemper reviewed Pratik Bhujel's Io\Terminal RFC and found two bugs. Pratik pushed fixes within a day, plus one he found himself, and the vote stays on hold.

Links: Io\Terminal RFC

Damian Jóźwiak planned the CSV extension vote for November 2nd. Tim Düsterhus asked him to wait after the security release, and questioned giving CSV its own top-level namespace, so Damian postponed it.

Links: CSV extension RFC

Sjoerd also proposed openssl_get_channel_binding, which ties a login to the TLS connection it runs over, so mail and database clients can offer the PLUS variants of SCRAM logins. Tim asked why it returns null instead of throwing.

Links: openssl_get_channel_binding RFC

On blocking server-side request forgery in curl, Nicolas Grekas wrote "Yes, please make this happen!", for Symfony's HTTP client, and Levi Morrison asked why it should be curl-only rather than cover streams too.

Links: SSRF protection in curl

Máté Kocsis is keeping the length limit in his query parameters RFC, citing the recent CVEs.

Links: Query parameter manipulation RFC

Abbas proposed async and await keywords on top of Fibers, and Frode Børli replied that PHP should go the way of Go, choosing concurrency at the call site.

Links: async/await on top of Fibers

A developer who validates JSON from AI models asked the pattern matching RFC to keep a missing key different from null.

Links: Pattern matching RFC

And a proposal to call scalar extension methods without parentheses got a strong minus one from Rowan Tommins, for saving two characters per call.

TL;DR (11:15)

So that's the week. After last week's critical bugs, a call to freeze PHP until it has a formal spec met pushback, and Larry Garfield called the bug-fix bottleneck a money problem. Windows users have rebuilt packages to install, and php.net suggests one session setting until the next release. A year of data showed how much a newcomer's first pull request depends on a fast reply, Frode Børli's Scope RFC would give every request an identity, and array_partition arrived with Tim's support. Links below.

The PHP Foundation funds more than half of ongoing php-src commits, so if you use the language, maybe consider donating at opencollective.com/phpfoundation — or try guilting your employer into it.

If you found this useful, a like or a comment helps more people find it. And if you missed last week's episode, where two critical PHP vulnerabilities leaked a day before their fix, that's a good one to watch next. Thanks again to Scalpels.app for supporting this week's episode. We're Artisan Build. See you next week.

submitted by /u/ProjektGopher to r/PHP
[link] [comments]
  •  

PHP CLI workers don’t share opcache, so I made them: 70–80% less memory for Laravel queues

PHP's CLI doesn't share opcache between separately started processes, so every long-running worker compiles your whole app into its own private memory. With 8 Laravel queue workers that's 8 copies of the same compiled code, often 50–80 MB each.

I built queue-prefork to fix that for Laravel's queue:work and Horizon:

  • A small template process starts with opcache and no app code.
  • Each worker is forked from it with pcntl_fork() and then boots the app itself from the normal artisan entry. So nothing booted is inherited: no DB or Redis connections, sockets, singletons or RNG state. Only the compiled code is shared, through opcache's shared memory.
  • The pid your process manager started stays (a tiny /bin/sh stub for queue:work), so supervisord or systemd signals, timeouts and restarts behave as before.

Side-by-side benchmark, two identical Docker stacks on the same job stream, Laravel 13 with ~45 packages, 1 h each:

Setup Stock Prefork
8 × queue:work, typical jobs 645 MB 192 MB (−70%)
8 × queue:work, idle 455 MB 102 MB (−78%)
8 × queue:work, heavy jobs 1,025 MB 524 MB (−49%)
Horizon, 6 supervisors 1,279 MB 240 MB (−81%)

Same throughput, 0 failed jobs, and less CPU, since new workers don't recompile anything. If any safety check fails, workers run as stock and the package tells you why.

Linux only for production; Laravel 11–13. MIT: https://github.com/tevkert/queue-prefork

Happy to answer questions about the fork and opcache side.

submitted by /u/Tevkert to r/PHP
[link] [comments]
  •  

One week after the PHP2Shell fix: about half of live sites on 8.2–8.5 show a patched release, and under 1% on 5.4–7.3 have moved. How we counted

I work at IPinfo, where we scan the IPv4 and IPv6 Internet. On October 22, the day after the fixed releases (8.5.12, 8.4.27, 8.3.36, 8.2.35), we started re-checking the same 1.46 million addresses that show a PHP version every day.

Where they started. In our October 14–15 scan, 1,105,160 addresses showed a PHP version. 409,494 of them (37%) ran 5.4–7.3, which is affected and gets no free official fix.

One week later. Of the servers that weren’t yet on a patched release on October 22:

  • Live sites on 8.2–8.5: 36.5% patched on day one, 47.5% by October 28 (41,707 of 87,865). Almost everything happened on the first day.
  • Default pages, panels and devices on 8.2–8.5: 23.0%.
  • Live sites on 5.4–7.3: 0.95% moved to a patched release (1,249 of 131,024).

Among servers still showing a vulnerable version, 47% now run 7.3 or older. For comparison, Wiz reported 5.7% for its customers’ cloud machines. The open Internet has a much longer tail.

How we counted:

  • Patched means the version string shows 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 or later, lowest version per address.
  • We left out addresses that show PHP only on hosting control-panel ports (2082, 2083, 2086, 2087, 2095, 2096), and blocks where 64 or more addresses in a /24 (or /64) send the identical response. That’s one machine answering for many.
  • “Live site” means the page looked like a site in use in our October 14–15 scan, not a default page, login panel or device.
  • We dropped October 26 from the series. One large host’s proxy hid PHP versions on tens of thousands of servers for that day only.

Caveats:

  • Some hosts (GoDaddy, cPanel’s EasyApache packages) and distributions backport fixes without changing the version number, and TuxCare sells patched builds for 5.x–8.1. So these numbers are minimums.
  • We measure versions, not break-ins. CISA added PHP2Shell to its known-exploited list on October 26, but we can’t see who was attacked.

Happy to answer questions on the method. I write these up in a short brief: https://ipinfo.io/blog/internet-brief-1?utm_source=reddit_r_php&utm_medium=social&utm_campaign=php2shell

submitted by /u/seremot to r/PHP
[link] [comments]
  •  

Something feels off about this subreddit lately

I don't know if it's just me, but ever since last week (October 21 / php2shell), this subreddit has felt completely out of control.

It honestly doesn't feel like the same community I used to know anymore, and at least to me, it seems to be heading in the wrong direction.
I get that the php2shell caused a lot of attention, and that new people are naturally going to have questions about it. But at the same time, there seems to have been a noticeable increase in spam and low-effort posts that end up sitting at 0 upvotes.

Is it just me?

(I propably go touch a some grass for a moth and hope its just temporary)

submitted by /u/goodwill764 to r/PHP
[link] [comments]
  •  
❌