Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions resources/ATTRIBUTION.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@

* missing-3-confusion.svg
Created by hand using https://www.svgviewer.dev/

* extra-5-confusion.svg
Created by hand using https://www.svgviewer.dev/
Based on my previous work on missing-3-confusion.svg
51 changes: 51 additions & 0 deletions resources/extra-5-confusion.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,7 @@
<url>
<loc>https://scherzer.dev/Blog/20251029-longhorn-php</loc>
</url>
<url>
<loc>https://scherzer.dev/Blog/20251113-release-candidate-5</loc>
</url>
</urlset>
131 changes: 131 additions & 0 deletions src/Blog/posts/20251113-release-candidate-5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
title: The Story of PHP 8.5.0 Release Candidate 5
extra-classes:
- blog-page--sidebar-image
---

# The Story of PHP 8.5.0 Release Candidate 5

PHP 8.5.0 Release Candidate 4, [announced][rc4-announce] last week, was expected
to be the last release candidate (RC) of the PHP 8.5.0 development cycle, before
the general availability release next week. But, earlier today I
[announced the release of PHP 8.5.0 RC5][rc5-announce]. So, why was an extra
release candidate needed?

![Extra RC5 confusion](/resources/extra-5-confusion.svg)

When PHP 8.5.0 RC4 was tagged and announced, it was expected to be the last
release candidate before the general availability (GA) release of 8.5.0 next
week. But, a few bugs surfaced that seemed to warrant having their fixes
included in the GA release.

Technically, the GA release could have bug fixes that were never included in
any of the testing releases. But, that would result in releasing code that was
only really tested with GitHub's continuous integration. Such a situation should
be avoided.

## Bugs
Our goal, as always, is to ship releases with no known bugs. But, at some point,
we have to draw a line and delay further fixes until the next patch release,
in this case PHP 8.5.1. New bugfix releases of supported versions of PHP
(currently PHP 8.3 and PHP 8.4, soon to include PHP 8.5) are announced every
four weeks as bugs are continuously addressed. Neither PHP 8.5.0 RC5 nor the
eventual GA release are expected to be entirely free from bugs, but they should
be free from issues that would prevent upgrading from earlier versions of PHP.

The great thing about people testing the release candidates before the GA
release is packaged is that we can change things when issues are found. Which
is exactly what we are doing here, thanks to user reports.

Among the many changes coming in PHP 8.5, three specific changes led to
bugs that we thought warranted addressing before the GA release. These were

* the creation of the new ext/uri extension
* the addition of a new INI option, `max_memory_limit`
* the deprecation of returning non-strings from output handlers

Thanks to volunteers who tested out the release candidates, and continued
developer attention, we found and addressed the following issues

* [#20431][gh-20431]: `Uri\Rfc3986\Uri::setHost(null)` turns empty path into `/`
* No distinction between empty and missing query/fragment when using
`Uri\WhatWg\Url::getQuery()` and `Uri\WhatWg\Url::getFragment()`
* [#17951][gh-17951]: `memory_limit` is not always limited by `max_memory_limit`
* [#20384][gh-20384]: Confirm if `ob_gzhandler` is impacted by `ob_start`
handler changes

For the `ob_gzhandler` issue, the fix was actually to revert the underlying
changes to `ob_start`. As part of the [PHP 8.4 deprecations RFC][rfc-84-dep],
a proposal was accepted to emit deprecation warnings when an output handler
returned something other than a string. That deprecation wasn't implemented for
the 8.4 release, but I came across the unimplemented RFC and
[implemented it][gh-18932] back in July, in time for inclusion in the PHP 8.5
release. The issue filed here was asking for some clarification when the output
handler was the [`ob_gzhandler`][fn-ob_gzhandler] function from the zlib
extension. After some discussion on the issue, it looked like a bugfix was
going to be applied to improve the behavior of the deprecation warnings, but
eventually it was decided to just revert the deprecation entirely. I'm not sure
to what extent my reluctance to revert the deprecation was based on having been
the one to originally implement the deprecation, rather than wanting to avoid
changes to the release so close to it being finalized in my role as a release
manager.

Initially, these were addressed the same way bugfixes generally are - a patch
against the relevant version of PHP, in this case PHP 8.5. There are no special
restrictions on merging commits to the branches of supported PHP versions - any
developer with access can merge the changes.

## Cherry Picking
However, to be able to include the fixes in PHP 8.5.0, a release manager (in
this, me) needed to also apply the changes to the `PHP-8.5.0` branch.
Technically, all of the release managers, even for a different version of PHP,
have access to the patch-specific branches for PHP 8.5, but my understanding is
that these branches are essentially "owned" by the PHP 8.5 release manager. In
other words, if a PHP 8.4 release manager had sent one of these bug fixes, in
theory they *could* have also updated the `PHP-8.5.0` branch, but they probably
would not have.

In addition to adding the commits to the `PHP-8.5.0` branch, I also needed to
make sure that GitHub ran the standard suite of tests for the cherry-picked
changes. GitHub is configured to run tests when commits are pushed to the
`master` and version-specific branches (e.g. `PHP-8.5`), but not the
patch-specific branches like `PHP-8.5.0`. Thankfully, the workflow for tests
could also be triggered manually, specifying what branch to run against - I was
able to thus tell GitHub to run the tests for the `PHP-8.5.0` branch.
Thankfully, the tests all passed - had they failed, I'm not sure what I would
have done.

For a full comparison of the changes between RC4 and RC5, you can check the
[comparison between the two tags][gh-comp-tags] on GitHub.

## Process
Once it was decided to add another release candidate, and the relevant changes
were present in the `PHP-8.5.0` branch, the process to actually tag and announce
the new release was essentially the same as normal. For those interested, my
[blog entry explaining the reasons for PHP 8.5.0alpha4][blog-alpha4] includes
a description of the process. The main difference was that, since there was
already a patch-level branch created for the 8.5.0 GA release, the RC5 tag was
created from that branch, rather than the main `PHP 8.5` branch.

## Looking Ahead
Fingers crossed, RC5 should be the last release candidate needed, and we will
be able to announce the general availability of PHP 8.5 next week as scheduled.
If not, we would need to delay by another **four weeks** in order to align with
the release cycle of the maintenance branches.

I'm also giving [a presentation about PHP 8.5 changes][talk-mergephp] later
today through MergePHP. I need to make sure that my slides are updated to
account for the changes we just made - specifically, I was going to talk about
the output handler deprecation that is now no longer happening.

[rc4-announce]: https://www.php.net/archive/2025.php#2025-11-06-1
[rc5-announce]: https://www.php.net/archive/2025.php#2025-11-13-1
[gh-20431]: https://github.com/php/php-src/issues/20431
[gh-17951]: https://github.com/php/php-src/issues/17951
[gh-20384]: https://github.com/php/php-src/issues/20384
[rfc-84-dep]: https://wiki.php.net/rfc/deprecations_php_8_4
[gh-18932]: https://github.com/php/php-src/pull/18932
[fn-ob_gzhandler]: https://www.php.net/manual/en/function.ob-gzhandler.php
[gh-comp-tags]: https://github.com/php/php-src/compare/php-8.5.0RC4..php-8.5.0RC5
[blog-alpha4]: ./20250801-no-alpha-3
[talk-mergephp]: https://www.mergephp.com/meetups/2025/11/13/php-8-5-new-features-from-the-source.html
8 changes: 5 additions & 3 deletions tests/data/Home.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
Computer Science and Political Science and graduating <em>magna cum laude</em> in 2024 with a Bachelor of Science degree. As part of my work in Computer
Science, I chose to write an honors thesis in my senior year, see <a href="./Thesis">here</a> for details. I continued at Tufts for graduate school, graduating in 2025 with
a Master of Science in Computer Science degree.</p><p>See the links in the navigation bar above for more information about my
experience.</p><h2 class="subsection-header">Contact</h2><ul><li><a href="https://www.linkedin.com/in/daniel-scherzer-520539263/" target="_blank" class="external-link">LinkedIn</a></li><li>Email: <code>daniel.e.scherzer@gmail.com</code></li></ul><h2 class="subsection-header">Blog</h2><p>I also have a blog. You can see a full index of my posts <a href="/Blog">here</a>. My latest blog post is: </p><div class="blog-preview"><h3>Longhorn PHP 2025</h3><span class="blog-preview-date">Wednesday, 29 October 2025</span><p>Last week, I attended the Longhorn PHP conference in Austin, Texas. I had the
opportunity to meet with a slew of open source contributors, listen to some
amazing talks, and even present my own. <a href="/Blog/20251029-longhorn-php">Continue reading...</a></p></div></div><div class="des-footer"><div class="des-footer--content">Content is © 2025 Daniel Scherzer</div></div></body></html>
experience.</p><h2 class="subsection-header">Contact</h2><ul><li><a href="https://www.linkedin.com/in/daniel-scherzer-520539263/" target="_blank" class="external-link">LinkedIn</a></li><li>Email: <code>daniel.e.scherzer@gmail.com</code></li></ul><h2 class="subsection-header">Blog</h2><p>I also have a blog. You can see a full index of my posts <a href="/Blog">here</a>. My latest blog post is: </p><div class="blog-preview"><h3>The Story of PHP 8.5.0 Release Candidate 5</h3><span class="blog-preview-date">Thursday, 13 November 2025</span><p>PHP 8.5.0 Release Candidate 4, <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://www.php.net/archive/2025.php#2025-11-06-1">announced</a> last week, was expected
to be the last release candidate (RC) of the PHP 8.5.0 development cycle, before
the general availability release next week. But, earlier today I
<a rel="noopener noreferrer" target="_blank" class="external-link" href="https://www.php.net/archive/2025.php#2025-11-13-1">announced the release of PHP 8.5.0 RC5</a>. So, why was an extra
release candidate needed? <a href="/Blog/20251113-release-candidate-5">Continue reading...</a></p></div></div><div class="des-footer"><div class="des-footer--content">Content is © 2025 Daniel Scherzer</div></div></body></html>
6 changes: 5 additions & 1 deletion tests/data/blog-index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<!DOCTYPE html>
<html lang="en"><head><link rel="icon" href="data:,"><meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"><link rel="stylesheet" type="text/css" href="/resources/default-styles.css"><title>Blog index</title><link rel="stylesheet" type="text/css" href="/resources/blog-styles.css"></head><body><div class="des-navbar"><a href="/Home">Home</a><a href="/files/Resume.pdf">Résumé</a><a href="/OpenSource">Open Source</a><a href="/Work">Work</a><strong class="des-strong-page-link">Blog</strong></div><div class="content-wrapper"><h1>Blog index</h1><div class="blog-preview"><h2>Longhorn PHP 2025</h2><span class="blog-preview-date">Wednesday, 29 October 2025</span><p>Last week, I attended the Longhorn PHP conference in Austin, Texas. I had the
<html lang="en"><head><link rel="icon" href="data:,"><meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"><link rel="stylesheet" type="text/css" href="/resources/default-styles.css"><title>Blog index</title><link rel="stylesheet" type="text/css" href="/resources/blog-styles.css"></head><body><div class="des-navbar"><a href="/Home">Home</a><a href="/files/Resume.pdf">Résumé</a><a href="/OpenSource">Open Source</a><a href="/Work">Work</a><strong class="des-strong-page-link">Blog</strong></div><div class="content-wrapper"><h1>Blog index</h1><div class="blog-preview"><h2>The Story of PHP 8.5.0 Release Candidate 5</h2><span class="blog-preview-date">Thursday, 13 November 2025</span><p>PHP 8.5.0 Release Candidate 4, <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://www.php.net/archive/2025.php#2025-11-06-1">announced</a> last week, was expected
to be the last release candidate (RC) of the PHP 8.5.0 development cycle, before
the general availability release next week. But, earlier today I
<a rel="noopener noreferrer" target="_blank" class="external-link" href="https://www.php.net/archive/2025.php#2025-11-13-1">announced the release of PHP 8.5.0 RC5</a>. So, why was an extra
release candidate needed? <a href="/Blog/20251113-release-candidate-5">Continue reading...</a></p></div><div class="blog-preview"><h2>Longhorn PHP 2025</h2><span class="blog-preview-date">Wednesday, 29 October 2025</span><p>Last week, I attended the Longhorn PHP conference in Austin, Texas. I had the
opportunity to meet with a slew of open source contributors, listen to some
amazing talks, and even present my own. <a href="/Blog/20251029-longhorn-php">Continue reading...</a></p></div><div class="blog-preview"><h2>Project Euler in Rust</h2><span class="blog-preview-date">Friday, 19 September 2025</span><p>After writing the obligatory &quot;Hello, World!&quot;, I wanted to work on something
more substantial in Rust. When I learn a new programming language, my go-to
Expand Down