Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Shipping PHP 8.5

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

Shipping PHP 8.5

A Release Manager’s view on how a new PHP version comes together. Discussing the features in PHP 8.5 and how releasing and contributing to a PHP version works.

Showcasing how numerous individuals and the PHP Foundation shape a new PHP version.

Avatar for Volker Dusch

Volker Dusch

May 14, 2026

More Decks by Volker Dusch

Other Decks in Technology

Transcript

  1. Today How does a new PHP version come together? My

    13 months as an 8.5 RM The features in 8.5 and the humans behind them Preparing for PHP 8.6 Contributing to PHP and the ecosystem
  2. About me ~20 years of PHP I work on web

    applications with long life cycles Working at @Tideways on PHP performance tooling Head of Engineering and "Full Stack" Engineer
  3. About Tideways Effortless Performance Insights with Zero Code Changes Small

    self founded company from Germany Fully focused on the PHP ecosystem Great support from them in my RM work Other contributions to PHP Decided to sponsor phpday after my talk was accepted
  4. Timeline Every year a new PHP version is released The

    General Availability (GA) release happens in the 3rd week of November Let's dive into how that plays out
  5. What does an RM do? One PHP release every 4

    weeks, more pre-GA Work split between two people Package our php-src branch, getting it ready for people "Tag, build, test, sign, upload, announce" Coordination around the feature freezes What goes in, what is a BC issue, what is a bugfix? Deal with post-RC regressions https://github.com/php/php-src/blob/master/docs/release-process.md
  6. Timeline - Pre GA RM voting ended on the 16th

    of April 2025 We'll talk about the voting process later showcasing the 8.6 election Alpha 1 on the 3rd of July 2025 3 alphas, 3 betas and 5 RCs before GA 4 planned RCs, some last minute findings 1 skipped Alpha due to a packaging error Plenty of time to test https://scherzer.dev/Blog/20250801-no-alpha-3 https://scherzer.dev/Blog/20251113-release-candidate-5
  7. Timeline - Post GA A release manager sticks with their

    release for the whole 4.5 years Released on 20 November 2025 2 years of active support 2 more years security PHP 8.5 will be EOL (end of life) on the 1st of January 2030 8.2 is the oldest version with security support https://www.php.net/supported-versions.php
  8. What's included in a release Current state of development is

    branched into a new release version once a year What's in on the 22nd of September 2026 (two days before RC1) will roughly be what's in PHP 8.6
  9. People build them There is no one organization that drives

    PHP. Individuals do. Most changes are done without an RFC Language maintenance is essential work Karma / Commit-Bit to php-src for maintenance If a PR looks non-trivial, an RFC can be requested Policy updates also follow the RFC process
  10. RFCs are community work People come together to.. discuss RFCs

    on the list and help shape them propose RFCs Ideas are cheap, language design is hard Features wouldn't be nearly as good without the list implement them review the code changes vote on RFCs test alphas, betas and RCs and report bugs
  11. RFC process https://wiki.php.net/rfc/howto Have an idea Validate through discussion Write

    an RFC Basically a form to carefully fill out A reference implementation helps, you can find help with that Discuss on the mailing list Voting Technical review on GitHub
  12. Examples from 8.5 Let's look at just some of the

    8.5 RFCs Each feature lists the authors, implementors and reviewers There are too many people involved in the discussions to list them all, which is great!
  13. URI Parsing API Author: Máté Kocsis Implementation & Review: Máté

    Kocsis, Nora Dossche, Tim Düsterhus RFC 3986: Defines URIs WHATWG: Specifies how browsers should treat URLs Web Hypertext Application Technology Working Group A year long story of diligence and collaboration that could be its own talk https://wiki.php.net/rfc/url_parsing_api
  14. URI Parsing Example Same with Uri\Rfc3986\Uri $url = new Uri\WhatWg\Url("https://example.com");

    $url = Uri\WhatWg\Url::parse("https://example.com"); // Throws Uri\WhatWg\InvalidUrlException $url = new Uri\WhatWg\Url("invalid url");
  15. WHATWG example For URLs to render in a browser. Use

    WHATWG. For everything else use RFC 3986. <?php $url = new Uri\WhatWg\Url( "HTTPS://user:pass@exämple.com:443" . "/foobar?abc=abc#def" ); echo $url->getScheme(); // https echo $url->getUsername(); // user echo $url->getPassword(); // pass echo $url->getAsciiHost(); // xn--exmple-cua.com echo $url->getUnicodeHost(); // exämple.com echo $url->getPort(); // 443 echo $url->getPath(); // /foobar echo $url->getQuery(); // abc=abc echo $url->getFragment(); // def 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  16. With-ers <?php $url = new Uri\WhatWg\Url("https://example.com/"); $url = $url->withQuery("?foo"); $url

    = $url->withFragment("#bar"); echo $url->getQuery(); // foo echo $url->getFragment(); // bar 1 2 3 4 5 6 7
  17. Closures in Constant Expressions Authors: Tim Düsterhus, Volker Dusch Implementation

    & Review: Tim Düsterhus, Volker Dusch, Ilija Tovilo, Arthur Kurbidaev https://wiki.php.net/rfc/closures_in_const_expr final class Locale { #[Validator\Custom(static function ($languageCode) { return \preg_match('/^[a-z][a-z]$/', $languageCode); })] public string $languageCode; } #[DataProviderClosure(static function () { yield 'test data' => ['bar', 'baz']; })] public function testFoo($one, $two) {
  18. First Class Callables in constant expressions Authors: Tim Düsterhus, Volker

    Dusch Implementation & Review: Tim Düsterhus, Volker Dusch, Ilija Tovilo, Dmitry Stogov Following the last RFC: https://wiki.php.net/rfc/fcc_in_const_expr final class LogEntry { public string $message; #[Serialize\Custom(self::myMethod(...))] public string $severity; }
  19. PHPUnit data provider IDE Autocomplete. "Method not found" static analysis.

    class MyTest { // Before #[DataProviderExternal(SharedTestData::class, 'dataProvider')] #[DataProvider('dataProvider')] // After #[DataProviderClosure(SharedTestData::dataProvider(...))] #[DataProviderClosure(self::dataProvider(...))] public testThing($arg1, $arg2, $arg3): void { } } https://github.com/sebastianbergmann/phpunit/pull/6526
  20. Pipes Author: Larry Garfield Implementation & Review: Larry Garfield, Gina

    Peter Banyard, Arnaud Le Blanc, Tim Düsterhus Trying to make function call chains more readable. https://wiki.php.net/rfc/pipe-operator-v3 $greeting = " Hello World "; $length = $greeting |> trim(...) |> strlen(...); 2 3 4 5 $greeting = " Hello World "; $length = strlen(trim($greeting)); 2 3
  21. Remember how PHP used to look? $greeting = 'hello world';

    $greeting = implode( ' ', array_map( 'ucfirst', explode( ' ', $greeting, ) ) ); var_dump($greeting); 1 2 3 4 5 6 7 8 9 10 11 12
  22. Using multiple assignments Now expressed as pipes $greeting = 'hello

    world'; $greeting = explode(' ', $greeting); $greeting = array_map(ucfirst(...), $greeting); $greeting = implode(' ', $greeting); var_dump($greeting); 1 2 3 4 5 $greeting = 'hello world' |> (fn(string $greeting) => explode(' ', $greeting)) |> (fn(array $parts) => array_map(ucfirst(...), $parts)) |> (fn(array $parts) => implode(' ', $parts)); var_dump($greeting); 1 2 3 4 5 6
  23. Processing pipeline The statements are treated as nested function calls.

    Exceptions work by leaving the whole pipe. public function totalCostCalculator(Price $listPrice): Price { return $price |> $this->addShipping(...) |> $this->applyCoupons(...) |> $this->applyMemberDiscounts(...) |> $this->addTax(...) }
  24. The best it can be The vote for pipes ended

    33:7. Well over the needed 2/3 majority. Even people who ended up voting against it helped in the discussion to make it the best version of the feature it could possibly be. Despite a lot of eyes, this still received fixes in the RC- phase requiring a post-RFC syntax adjustments. Thanks to Derick finding this while trying to make this work in Xdebug and finding issues.
  25. php --ini=diff Implementation & Review: Tim Düsterhus, Gina Peter Banyard,

    Jakub Zelenka Remember your CLI and web server settings might be different! ➜ php --ini=diff Non-default INI settings: html_errors: "1" -> "0" implicit_flush: "0" -> "1" max_execution_time: "30" -> "0"
  26. Non existent settings are ignored php -d opcache.enable=1 -d opcache.enable_cli=1

    \ -d opcache.opt_debug_level=0x20000 --ini=diff If there is no output, something is missing. # We've been missing: zend_extension=opcache.so # ... except with PHP 8.5 that's solved as well
  27. Always on OPcache Authors: Tim Düsterhus, Arnaud Le Blanc, Ilija

    Tovilo Implementation & Review: Arnaud Le Blanc, Nora Dossche, Dmitry Stogov, Tim Düsterhus Statically built into PHP. Easier "single binary" setups. Simplified production setups. No more "is OPcache available?" checks. https://wiki.php.net/rfc/make_opcache_required
  28. Attributes on Constants Author: Daniel Scherzer Implementation & Review: Daniel

    Scherzer, Dmitry Stogov, Ilija Tovilo, Tim Düsterhus, Nora Dossche https://wiki.php.net/rfc/attributes-on-constants #[\Deprecated] const FOO = 1; echo FOO; // Deprecated: Constant FOO is deprecated in $file on line 6
  29. Error Backtraces v2 Authors: Eric Norris Implementation & Review: Eric

    Norris, Nora Dossche, Dmitry Stogov, Gina Peter Banyard, Jakub Zelenka, Calvin Buckley, Bob Weinand, Derick Rethans, Ilija Tovilo, Tim Düsterhus, Remi Collet We already had stack traces for undefined functions, classes and failed requires. Now we have them for: Timeouts Out of Memory errors Class redefinitions https://wiki.php.net/rfc/error_backtraces_v2
  30. Infinite loop example <?php set_time_limit(1); function bar() { foo(); }

    function foo() { for(;;) {} } (fn () => bar())();
  31. New with Backtraces PHP 8.4 PHP 8.5 // Fatal error:

    Maximum execution time of 1 second exceeded in... // Fatal error: Maximum execution time of 1 second exceeded in... // Stack trace: // #0 .../fatal-error-backtrace.php(4): foo() // #1 .../fatal-error-backtrace.php(11): bar() // #2 .../fatal-error-backtrace.php(11): {closure:/.../fatal-error-backtrace.php:11}() // #3 {main}
  32. #[\NoDiscard] Authors: Tim Düsterhus, Volker Dusch Implementation & Review: Tim

    Düsterhus, Nora Dossche, Ilija Tovilo, Dmitry Stogov Use return values or explicitly discarded them. https://wiki.php.net/rfc/marking_return_value_as_important function addOneHour(DateTimeInterface $x) { /* Missing return */ $x->modify('+1 hours'); } $x = new DateTimeImmutable('now'); addOneHour($x); // Warning: The return value of method DateTimeImmutable::modify() // should either be used or intentionally ignored by casting // it as (void), as DateTimeImmutable::modify() // does not modify the object itself
  33. Symfony HTTP-Client Example Communicate developer intent // This never throws

    as the evaluation is lazy! $response = $this->client->request( 'GET', 'https://api.github.com/repos/symfony/symfony-docs' ); try { // As suggested in the docs, ->getStatusCode() is called early // to block until request finished to handle errors (void) $response->getStatusCode(); } catch (\Exception $e) { // handle transport or HTTP exception } // Actual result handling happens somewhere else handleResult($response);
  34. Persistent Curl Handles Author: Eric Norris Implementation & Review: Eric

    Norris, Nora Dossche, Gina Peter Banyard, Tim Düsterhus, Máté Kocsis Connection reuse between curl requests across script runs (of the same worker process). https://wiki.php.net/rfc/curl_share_persistence_improvement
  35. array_first & array_last Author: Nora Dossche Implementation & Review: Nora

    Dossche, Tim Düsterhus https://wiki.php.net/rfc/array_first_last // A common, stable way to do this before: foreach ($array as $first) { break; } // Works, but changes the array pointer: $first = reset($array); // Takes up additional memory: $first = array_values($array)[0];
  36. It just works function array_first(array $array): mixed {} function array_last

    (array $array): mixed {} array_first([1 => 'a', 0 => 'b', 3 => 'c', 2 => 'd']); // 'a' array_last ([1 => 'a', 0 => 'b', 3 => 'c', 2 => 'd']); // 'd'
  37. Why only now? Because nobody built it before. RFC was

    voted in with 35:0. Discussion was short. Just makes sense. If you have an array_first grade improvement: Please build it. Let me know if you need help with the process :)
  38. Clone with Authors: Volker Dusch, Tim Düsterhus Implementation & Review:

    Volker Dusch, Tim Düsterhus, Nora Dossche, Ilija Tovilo Rounds out the readonly / immutable feature set Makes with-er style APIs much less awkward https://wiki.php.net/rfc/clone_with_v2 return clone($response, [ "statusCode" => 500, "reasonPhrase" => "Error", ]);
  39. PHP_BUILD_PROVIDER & PHP_BUILD_DATE No RFC needed Implementation & Review: Calvin

    Buckley, Tim Düsterhus, Peter Kokot, Jakub Zelenka, Gina Peter Banyard, Christoph M. Becker, Ayesh Karunaratne Where does your PHP come from? Useful for bug reports and debugging. docker run -it --rm php:8.5-cli \ php -r 'echo PHP_BUILD_DATE, PHP_EOL, PHP_BUILD_PROVIDER;' May 8 2026 19:23:57 https://github.com/docker-library/php
  40. Deprecations matter One collective RFC for voting: Authors: Gina Peter

    Banyard, Christoph M. Becker, Daniel Scherzer, Tim Düsterhus, Theodore Brown, Jorg Sowa, David Carlier, Jakub Zelenka, Nicolas Grekas, Volker Dusch, Calvin Buckley Full insights in UPGRADING: Cleaning up allows new features, future optimizations, and reduces maintenance burden. https://wiki.php.net/rfc/deprecations_php_8_5 https://github.com/php/php-src/blob/PHP- 8.5/UPGRADING
  41. The big cleanup RFC <3 Deprecations get added throughout the

    year. Recent releases have had one collection RFC. Great effort by Gina Peter Banyard managing all that. One discussion, lots of votes, keeps things focused, moving and effective. Gina will talk about deprecations tomorrow.
  42. Release Managers Elections Three RMs per release. 8.5 we had:

    Pierrick Charron - Senior Volker Dusch - Rookie Daniel Scherzer - Rookie https://wiki.php.net/todo/php85
  43. Roles One senior/hands-off RM to help that has done this

    before, helping onboarding people. Pierrick did a fantastic job getting us set up. Timeslots are very plannable. Two rookies/hands-on do the hands-on work, alternating releases.
  44. Eligibility No big up-front requirements Working knowledge of Git C/PHP-Internals

    is a plus Comfort with the internals community A few hours every two weeks More time required around in the GA phase Long term commitment
  45. Selection This is a high-trust based role with a long

    commitment Everyone who can vote on RFCs can vote here Many folks vote based on how they know and trust Mailing list participation, community involvement, RFCs, open source work, etc. Policies are open, accessible and always evolving through RFCs: https://wiki.php.net/rfc/release_manager_selection_policy
  46. Interested for next year? Come talk to me afterwards or

    online You get to write an application and explain your reasoning Include your socials, build trust If that sounds interesting, go for it
  47. The 8.6 timeline I ran the voting for this year

    3 March 2026 - call for volunteers 31 March 2026 - vote opens 15 April 2026 - vote is tallied Ongoing RM onboarding organized by the Senior (hands-off) RM and the PHP Infra Team ~2 July 2026 - Alpha 1 ~19 November 2026 - planned GA https://wiki.php.net/todo/php86
  48. How the vote works Seven people volunteered for the hands-on

    work. The hands-off/senior slot ran unopposed. 28 people voted. Single Transferable Vote on the wiki Voters rank candidates in order of preference Lowest get eliminated, votes redistributed Two rookies and one senior get the role
  49. The 8.6 result Hands-off: Daniel Scherzer (8.5 RM) Hands-on: Matteo

    Beccati Hands-on: Joe Ferguson https://wiki.php.net/todo/php86
  50. Packaging PHP The PHP project ships source code only. Someone

    out there builds the binaries you're running. Remi Collet - RHEL and Fedora RPMs Remi does so much more for the project Ondřej Surý - Debian and Ubuntu (deb.sury.org) Christoph M. Becker (cmb) - Windows builds Shivam Mathur - Homebrew & setup-php GHA Communities: docker-library/php maintainers And many more
  51. What packagers actually do It's not just ./configure && make.

    Build across versions, architectures and SAPIs Maintain hundreds of extensions on top of php-src Find bugs early, often before RC File fixes upstream Look at Remi's name on bug reports and PR reviews.
  52. PIE 1.4.2 Meet the new PECL: 🥧 Extension distribution via

    Packagist. pie install apcu/apcu pie install # Find unmet dependencies from composer.json gh release download --repo php/pie --pattern pie.phar gh attestation verify --repo php/pie pie.phar
  53. FrankenPHP as part of the PHP GitHub org Created by

    Les-Tilleuls.coop founder Kévin Dunglas Supported by the PHP Foundation since May 2025 A new single binary runtime for PHP, using Caddy Think Apache with mod_php but with Caddy DX HTTP 103 support, static binaries, worker mode php-fpm continues to be a first class citizen https://frankenphp.dev
  54. Foundation work A central place to fund work on PHP

    Pay developers, accept grants, have a voice in the language community https://thephp.foundation https://thephp.foundation/structure/ https://opencollective.com/phpfoundation
  55. Leadership in 2026 Roman Pronskiy, founding Executive Director (ED), stepped

    down as ED in early 2026. He stays on the Board, representing JetBrains. Elizabeth Barron took over as ED on the 27th of February 2026. https://thephp.foundation/blog/2026/02/27/welcoming-elizabeth-barron-new-executive- director/
  56. A new director Board ran an application process, and I

    couldn't be happier with whom they picked. A long time member of the PHP community. "Working Together on the Future of PHP": Public calendar to book time with her Direct email contact Asked for goals, motivations, pain points, and stories https://thephp.foundation/blog/2026/03/05/working-together-on-the-future-of-php/
  57. The listening tour ~60 people in 18 countries over two

    months. Core developers, ecosystem maintainers, user group organizers, OSS foundation leaders. https://thephp.foundation/blog/2026/04/16/integrating-community-feedback-into- foundation-strategy-part1/ Her calendar and the inbox are still open.
  58. Thank you Slides will be at I sometimes talk PHP

    on Mastodon @edorian.phpc.social https://speakerdeck.com/edorian https://phpc.social/@edorian