{"slug": "this-week-in-php-internals-nov-5-2026", "title": "This Week in PHP Internals | Nov 5, 2026", "summary": "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.", "body_md": "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.\n\nHello 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,*\n\nAI 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).\n\nA 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.\"\n\nTim 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.\n\nAnd 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.\n\n**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)\n\nThis 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.\"\n\nSo 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.\n\nPierre 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.\"\n\n**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)\n\nbcrypt 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.\n\nKamil 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.\n\nSjoerd 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.\"\n\n**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)\n\nLarry 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.\n\nHe 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.*\n\nRowan 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.\n\n**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)\n\nPHP'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.\"\n\nHe 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.\n\n**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)\n\nComments 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.\n\nThe 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.\n\nHe 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.\n\n**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)\n\nTwo 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.\n\n**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)\n\nQuick 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.\n\n**Links:** [CSV extension RFC](https://wiki.php.net/rfc/csv_extension) · [Ignace Nyamagana Butera](https://news-web.php.net/php.internals/132957)\n\nFor 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.\n\n**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)\n\nSjoerd's `openssl_get_channel_binding` now throws an exception instead of returning null, answering Tim's question from last week.\n\n**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)\n\nXavier Leune wants SSRF protection in `curl` first, so it lands in PHP 8.7, and maybe streams in a later RFC.\n\n**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)\n\nChris 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.\n\n**Links:** [grapheme_str_pad() RFC](https://wiki.php.net/rfc/grapheme_str_pad) · [php-src #25179](https://github.com/php/php-src/pull/25179)\n\nOn 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.\n\n**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)\n\nArtem Ukrainskiy got karma for an RFC on multi-pattern search and replace, with `Str\\Matcher` and `Str\\Replacer` classes.\n\n**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)\n\nAnd Andrey Andreev listed five oddities in the password hashing functions, with a plan to fix them over the next few months.\n\n**Links:** [Password hashing API](https://news-web.php.net/php.internals/132998)\n\nSo 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.\n\n[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.\n\nIf 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.", "url": "https://wpnews.pro/news/this-week-in-php-internals-nov-5-2026", "canonical_source": "https://dev.to/projektgopher/this-week-in-php-internals-nov-5-2026-51p8", "published_at": "2026-11-05 22:18:53+00:00", "updated_at": "2026-11-05 22:28:59.575021+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Kévin Dunglas", "FrankenPHP", "PHP", "Tim Düsterhus", "Larry Garfield", "Symfony", "Laravel", "Yii"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/this-week-in-php-internals-nov-5-2026", "markdown": "https://wpnews.pro/news/this-week-in-php-internals-nov-5-2026.md", "text": "https://wpnews.pro/news/this-week-in-php-internals-nov-5-2026.txt", "jsonld": "https://wpnews.pro/news/this-week-in-php-internals-nov-5-2026.jsonld"}}