This Week in PHP Internals | Nov 5, 2026 Kévin Dunglas, creator of FrankenPHP, proposed adding optional request-begin and request-end hooks to PHP's engine so worker-mode servers can reset per-request state between requests instead of reaching into PHP internals. He said the current approach is fragile, writing that "Each omission results in a cross-request leak or a memory safety bug," and cited FrankenPHP fixes this year for a session ID leaking to other clients, a use-after-free and a double free. After review with Tim Düsterhus, he narrowed the rule to state built from the incoming request and is drafting a short RFC with a patch. This year, FrankenPHP fixed a session ID leaking to other clients, a use-after-free, and a double free. Each one, its creator says, came from state that wasn't reset between two requests. That's because, he says, PHP's engine can't tell when a request ends, if the same script serves the next one. He wants to change that. Hello world, it's Thursday, November 5, 2026, and here's what happened This Week in PHP Internals. 14 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. The Free plan https://scalpels.app/pricing is zero dollars, forever, and new Laravel Cloud accounts get ten dollars in credit. Get started at scalpels.app https://scalpels.app . A few corrections from last week, most of them from Tim Düsterhus. On the CSV extension, Tim didn't ask Damian to wait until after the security release. The release had just happened, so people were likely busy patching their servers and hadn't caught up on the list, and he suggested waiting until things calmed down. And on calling extension methods without parentheses, we missed Rowan Tommins's main point. He wrote: "It also seems odd to propose it now, as an extension to something that doesn't even exist yet." Tim also caught two in last week's top story and quick hits. In Brian Nguyen's quote, "not deprecating integer" means the integer cast, which PHP just deprecated. And I said Sjoerd "postponed" openssl get channel binding . He proposed it, and it was brand new. Thanks, Tim. And a viewer on Bluesky pointed out that Brian's first mail said "I am not proposing freezing features or cosmetic deprecations." That's right. The embargo was in his second thread, the next morning, and our social posts skipped that distinction. Links: Tim Düsterhus on the CSV extension vote timing https://news-web.php.net/php.internals/132937 · Rowan Tommins on paren-less extension methods https://news-web.php.net/php.internals/132915 · Brian Nguyen's first mail https://news-web.php.net/php.internals/132917 · Brian Nguyen's second mail https://news-web.php.net/php.internals/132920 This week's top story: Kévin Dunglas, who created FrankenPHP, wants PHP's engine to know when a request ends. In worker mode, one long-running script handles request after request, keeping things like the Composer autoloader and framework services in memory. Symfony, Laravel and Yii support it natively. But the engine doesn't know, so FrankenPHP resets each request's leftovers by reaching into PHP's internals, which he calls fragile. He wrote: "Each omission results in a cross-request leak or a memory safety bug." So he proposed two optional hooks, request end and request begin, that a worker-mode server calls between requests, so each extension resets its own state. Servers that don't call them see no change. After talking it through with Tim Düsterhus, he narrowed the rule to state built from the incoming request, and he's writing a short RFC. Pierre asked whether last week's Scope RFC already covers this, and Larry Garfield asked how the two lifetimes would stay in sync. Kévin's answer: a scope gives a request an identity, but no clear end. So request begin would create the scope, and request end fires when the response is done, even if the scope lives on. He wrote: "The user-space and engine-space lifetimes stay in sync because the SAPI drives both." Links: Kévin Dunglas, the proposal https://news-web.php.net/php.internals/132960 · Narrowed after review https://news-web.php.net/php.internals/132976 · How it works with Scope https://news-web.php.net/php.internals/132978 · Draft patch https://github.com/dunglas/php-src/tree/request-boundary-hooks bcrypt only reads the first 72 bytes of a password, and now there are two RFCs to fix it. Andrey Andreev opened the second one this week, the alternative he asked for time to finish . PASSWORD BCRYPT WRAP hashes the password first, with cSHAKE256 by default or HMAC-SHA512, then runs bcrypt on the result. The RFC says that removes bcrypt's length and null byte limits. Kamil Tekiela objected that it shrinks bcrypt's input space and is open to hash shucking. Andrey replied that a prehash doesn't reduce bcrypt's security or input space, and that his salts keep the prehash separate from a plain hash. Tim Düsterhus asked for pseudo-code to settle it, and Andrey added it to the RFC on Monday. Sjoerd Langkemper, who wrote the other RFC, compared the two. His uses the same algorithm as Python's passlib and adds less code. Andrey's supports two prehashes in the PHC string format. Sjoerd thinks both are secure enough, and that one new algorithm is enough. He wrote: "It is unfortunate that we now have two RFCs that are so similar. Voting on them in isolation could result in an undesirable outcome." Andrey replied: "It just turned out this way, hopefully we don't have to look at it as mine against yours." Links: RFC: Add PASSWORD BCRYPT WRAP https://wiki.php.net/rfc/password bcrypt wrap · RFC: PASSWORD BCRYPT SHA256 https://wiki.php.net/rfc/bcrypt sha256 · Sjoerd Langkemper's comparison https://news-web.php.net/php.internals/132982 Larry Garfield is sold on the use case for Frode Børli's Scope RFC, but he's worried about code that doesn't know it's running inside a scope. A new scope starts with empty superglobals, so a legacy function that reads $ GET , called 20 functions deep, quietly stops working. He'd rather a new scope start from a clone of its parent's. He also expects everyone to hand-write WeakMap code to keep state per scope, and floated a Scoped attribute to automate it. In his own example, he forgot to initialize the WeakMap. He wrote: "So this is a pattern we need to work to make as fool-proof as possible, because we're all fools." No lies detected. Rowan Tommins welcomed a focused RFC that adds only what userland can't do, shared the WeakMap worry, and asked whether "context" would be a clearer name. Frode is keeping Scope, and says the WeakMap pattern takes getting used to, but isn't hard. He hasn't answered Larry yet. Links: RFC: Scope https://wiki.php.net/rfc/scope · Larry Garfield https://news-web.php.net/php.internals/132952 · Rowan Tommins https://news-web.php.net/php.internals/132983 · Frode Børli https://news-web.php.net/php.internals/132984 PHP's next date and time class would have no timezone at all. Tim Düsterhus and Derick Rethans's Time\Instant RFC is a point in time, and a clock returns one. Back after the security releases, Tim answered a reviewer's 15 points and kept the core design: the clock returns an Instant, not a date in some timezone. He wrote: "The timezone is a presentation-layer concern and stuff you 'present' to the user is generally expected to be coming from the database, rather than coming from the clock." He also turned down a raw Unix timestamp shortcut, to keep the API well-typed. The system clock can no longer be serialized, and two ideas moved to future scope: exposing the clock's resolution, and a faster, coarser system clock. There's no implementation pull request yet. Links: RFC: Time\Instant and Time\Clock https://wiki.php.net/rfc/time instant class · Tim Düsterhus's answers to the review https://news-web.php.net/php.internals/132953 · follow-up https://news-web.php.net/php.internals/132999 Comments and trailing commas in JSON were about to go to a vote. Otar Chekurishvili's RFC adds two opt-in flags for json decode and json validate , strict JSON stays the default, and Larry Garfield had no objections left. The vote was planned for Monday. Then Jakub Zelenka commented on the pull request: "I personally don't like non standard additions as they might complicate future optimizations in the parser." So Otar postponed the vote, the morning it was due to open. He replied on the pull request that both flags are opt-in, and a future fast parser could handle strict JSON and fall back when a flag is set. In strict mode, the change costs about 1.6% more CPU instructions, or 0.6% with a small scanner change. He'll answer the concern in the RFC, then announce a new vote. Links: RFC: JSON comments and trailing commas https://wiki.php.net/rfc/json comments trailing commas · Vote postponed https://news-web.php.net/php.internals/132988 · The pull request discussion https://github.com/php/php-src/pull/23336 Two votes closed this week, and one opened. Sjoerd Langkemper's RFC passed 27 to 1, so in PHP 8.7, hexdec , octdec , bindec and base convert throw on invalid characters instead of quietly ignoring them. Muhammed Arshid's Filter enums were declined, 2 to 16, with 2 abstentions. And Weilin Du's vote to let ini get all accept extension names in any case is at 12 to 0, with 2 abstentions. It closes November 16th. Links: Throw exception for invalid characters in number base functions accepted 27–1 https://wiki.php.net/rfc/throw error for invalid characters for number base · Add Filter\Filter and Filter\Flag Enums declined 2–16–2 https://wiki.php.net/rfc/invalid filter options · Case-insensitive extension names in ini get all open until Nov 16 https://wiki.php.net/rfc/case insensitive ini get all Quick hits. Ignace Nyamagana Butera likes the direction of the CSV extension, but says major points are unsolved: the top-level namespace, the lax and strict naming, and leaning on RFC 4180, which isn't an accepted standard. He suggests calling it Character Separated Value. Links: CSV extension RFC https://wiki.php.net/rfc/csv extension · Ignace Nyamagana Butera https://news-web.php.net/php.internals/132957 For binary parameters in PDO, Ilia Alshanetsky and Calvin Buckley now lean toward a flag instead of a new type, which would break drivers until each one updates. Links: PDO binary parameters RFC https://wiki.php.net/rfc/pdo binary · Ilia Alshanetsky https://news-web.php.net/php.internals/132985 · Calvin Buckley https://news-web.php.net/php.internals/132992 Sjoerd's openssl get channel binding now throws an exception instead of returning null, answering Tim's question from last week. Links: openssl get channel binding RFC https://wiki.php.net/rfc/openssl get channel binding · Sjoerd Langkemper's update https://news-web.php.net/php.internals/132993 Xavier Leune wants SSRF protection in curl first, so it lands in PHP 8.7, and maybe streams in a later RFC. Links: Xavier Leune on SSRF protection in curl https://news-web.php.net/php.internals/132955 · php-src 23657 https://github.com/php/php-src/pull/23657 Chris Abner Herrera Navarro went from a karma request to an RFC for grapheme str pad in under a week. It pads text by the characters you actually see, and Tim said it has exactly what he expected. Links: grapheme str pad RFC https://wiki.php.net/rfc/grapheme str pad · php-src 25179 https://github.com/php/php-src/pull/25179 On Máté Kocsis's query parameters RFC, Tim Düsterhus checked with the security team, and says a long query string can't make memory grow faster than the input, and the parameter count is already capped, so a separate length limit isn't needed. Links: Tim Düsterhus on the query string length limit https://news-web.php.net/php.internals/133001 · Query parameters RFC https://wiki.php.net/rfc/query params Artem Ukrainskiy got karma for an RFC on multi-pattern search and replace, with Str\Matcher and Str\Replacer classes. Links: Str\Matcher and Str\Replacer draft https://news-web.php.net/php.internals/132981 · php-src 25122 https://github.com/php/php-src/pull/25122 And Andrey Andreev listed five oddities in the password hashing functions, with a plan to fix them over the next few months. Links: Password hashing API https://news-web.php.net/php.internals/132998 So that's the week. Kévin Dunglas proposed hooks so PHP knows when a request ends in worker mode, and showed how they'd work with Scope. There are now two bcrypt fixes side by side, and Sjoerd says one is enough. Larry pushed back on Scope's empty superglobals, Tim kept the core of Time\Instant , and the JSON comments vote is on hold. Number base exceptions passed, and Filter enums didn't. Links below. The PHP Foundation https://thephp.foundation funds more than half of ongoing php-src commits, so if you use the language, maybe consider donating at opencollective.com/phpfoundation https://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 https://dev.to/projektgopher/this-week-in-php-internals-oct-29-2026-1m75 , where a call to freeze PHP until it has a formal spec got an answer about money, that's a good one to watch next. Thanks again to Scalpels.app https://scalpels.app for supporting this week's episode. We're Artisan Build. See you next week.