PHP 9.0: Release Date and Features You Must Know
- PHP 9.0
- PHP 9.0 - Release Date
-
Key Features of PHP 9.0
- 1. Predictable Increment/Decrement (++/--) Behavior
- 2. Exceptions for Unserialization Errors
- 3. Simplified Function Signatures
- 4. No Autovivification (Arrays from False)
- 5. Simplified String Interpolation
- 6. Warnings Become Fatal Errors
- 7. Removal of Deprecated Features
- 8. Removal of Partially Supported Callables
- 9. Stricter Explicit Casts (No More “Fuzzy” Casts)
- 10. Implicit Bool-to-String Coercion Becomes a TypeError
- 11. PHP 9.0 Drops 32-bit Builds
- 12. Enum Introspection Cleanup (get_declared_enums() and class_exists() semantics)
- 13. Dynamic Properties Become Errors (Unless Explicitly Allowed)
- 14. null to Non-Nullable Internal Scalar Arguments Throws TypeError
- 15. Removal of utf8_encode() and utf8_decode()
- 16. Removal of GET/POST Session IDs, use_trans_sid, and the SID Constant
- 17. Fuzzy Scalar Casts Become TypeError (Proposal)
- How to Prepare and Migrate
- Impact on the PHP Ecosystem
- Conclusion
PHP 9.0
PHP 9.0 is still in early planning, with no firm release date yet. In fact, core developers expect we’ll see PHP 8.5 and 8.6 before 9.0 arrives. In other words, the language’s evolution is gradual, but discussions and RFCs are already shaping PHP 9.0’s direction. The focus is on eliminating quirks and deprecated behaviors to make PHP code more predictable and robust. For example, one proposal is to forbid the odd behavior where incrementing a string like 'a9' produces 'b0'; instead PHP 9.0 will throw a TypeError. Similarly, silent warnings (e.g. from unserialization) will be promoted to exceptions, and deprecated features finally removed.
PHP 9.0 - Release Date
The PHP internals community has not yet announced a fixed release date for PHP 9.0. However, based on the typical cadence of major PHP releases (roughly every 2-3 years).
Key Features of PHP 9.0
PHP 9.0 introduces several major changes. Each feature below is supported by active RFCs and community discussion; here we explain them technically and show examples of the old vs. new behavior.
1. Predictable Increment/Decrement (++/--) Behavior
PHP has a history of surprising results with the ++ and -- operators. In PHP 8.x, incrementing a string or boolean silently converts types. For example:
$foo = 'a9';$foo++;echo $foo; // PHP 8.x outputs: "b0"
In PHP 9.0, this will throw a TypeError instead. Likewise, incrementing booleans or empty strings will behave more strictly. For instance:
$bar = true;$bar++;var_dump($bar); // PHP 8.x: bool(true), PHP 9.0: int(2)
and
$baz = '';$baz--; // In PHP 8.x this yields int(-1), but in PHP 9.0 it will throw a TypeError.
These changes are part of the “Path to Saner Increment” RFC. The goal is to make ++/-- more predictable. Under PHP 9.0:
-
No more implicit string wrapping (
'z'++or'a9'++won’t silently roll over). -
Booleans and
nullare treated as numeric: incrementingtruebecomes2rather thantrue. -
Empty strings no longer become numbers (empty string
''will not auto-convert to 0; doing so throws an error). - A new helper function
str_increment()is introduced for the old string behavior if needed.
These updates eliminate many subtle bugs. In practice, if your code relied on weird auto-incrementing, you’ll need to update it. Otherwise, most modern codebases will simply find ++/-- safer and more consistent.
RFC: Path to Saner Increment/Decrement operators
2. Exceptions for Unserialization Errors
In PHP 8.x, calling unserialize() on invalid data emits a warning and returns false. PHP 9.0 changes this to throw an exception. For example:
// PHP 8.x:$result = unserialize("invalid"); // emits a warning: "Error at offset 0", returns false // PHP 9.0:$result = unserialize("invalid"); // throws UnserializationFailedException
This is driven by the RFC “Improve unserialize() error handling”. By converting these warnings into UnserializationFailedException, PHP 9.0 makes error handling more explicit and secure. Developers can now use try/catch around unserialize(), avoiding hidden issues:
try { $obj = unserialize($data);} catch (UnserializationFailedException $e) { // handle error gracefully}
This change also ties into the Phasing out Serializable RFC: in PHP 9.0 the old Serializable interface will be removed, and payloads using the legacy “C” serialization format will be rejected. In short, PHP’s serialization becomes stricter and modernized.
RFCs: Improve unserialize() error handling · Phasing out Serializable
3. Simplified Function Signatures
Several built-in functions and methods will be split or renamed for clarity. A notable example is overloaded signatures. Take array_keys():
// PHP 8.x:$keys = array_keys($myArray); // all keys$keys = array_keys($myArray, 'value', true); // only keys with matching value // PHP 9.0 (example RFC):$keys = array_keys($myArray);$keys = array_keys_filter($myArray, 'value', true);
Here, PHP 9.0 introduces a new function (e.g. array_keys_filter) to handle the second mode, rather than having one function do two jobs. Another example is DatePeriod’s constructor:
// PHP 8.x:$period = new DatePeriod($start, $interval, $end);$period = new DatePeriod('R4/2012-07-01T00:00:00Z/P7D'); // PHP 9.0:$period = new DatePeriod($start, $interval, $end);$period = DatePeriod::createFromISO8601String('R4/2012-07-01T00:00:00Z/P7D');
The advantage is clearer APIs: each function does one thing, making code easier to understand. This transition will be staged over PHP 8.x (new functions in 8.3, deprecation warnings in 8.4, removal by 9.0).
RFCs: Deprecate functions with overloaded signatures · Deprecations for PHP 8.1
4. No Autovivification (Arrays from False)
PHP’s “autovivification” of arrays automatically turning a false or null into an array when you append to it will be disallowed in PHP 9.0. For example:
$arr = false;$arr[] = 2; // PHP 8.x: converts $arr to [2]
In PHP 9.0 this will error out:
$arr = false;$arr[] = 2; // PHP 9.0: Error - cannot use a scalar as an array
This change comes from the “Deprecate autovivification on false” RFC. Since other scalars like true or 0 already error, making false behave the same removes a special case. It eliminates a common bug where invalid data silently turned into an array. In practice, code should now explicitly initialize arrays (e.g. $arr = []) before appending, rather than relying on this quirk.
RFC: Deprecate autovivification on false
5. Simplified String Interpolation
PHP 9.0 will streamline how variables can be inserted into strings. Currently PHP supports several syntaxes:
- Double quotes with simple variable:
"$foo" - Braces around variable:
"{$foo}" - Braces after dollar:
"${foo}" - Variable variables in strings:
"${expr}"
PHP 9.0 will remove the “braces after dollar” and variable-variable syntax (the last two above). That means code like:
$foo = "world";echo "Hello ${foo}"; // This will cause an error in PHP 9.0
will no longer be allowed. Only the standard forms remain:
echo "Hello $foo"; // OKecho "Hello {$foo}"; // OK
The RFC “Deprecate ${} string interpolation” explains that the ${} syntax is confusing and rarely needed. By removing it, PHP encourages a single, clearer interpolation style. This also avoids subtle parsing issues in complex strings.
RFC: Deprecate ${} string interpolation
6. Warnings Become Fatal Errors
Several warnings in PHP 8.x will be escalated to errors in PHP 9.0. In particular, referencing undefined variables or properties which today emits a warning will instead produce a fatal error. For example:
// PHP 8.x:echo $undefinedVar;// Warning: Undefined variable $undefinedVar // PHP 9.0:echo $undefinedVar;// Fatal error: Uncaught Error: Undefined variable '$undefinedVar'
This change (via RFCs “Undefined Variable Error Promotion” and “Undefined Property Error Promotion”) means lax coding patterns will break. The intent is to catch mistakes early, e.g. typos or forgotten initializations, rather than letting them slide. Other warnings could also become errors, so developers must run code with E_ALL and fix any notices. In short, PHP 9.0 promotes cleaner, error-free code by default.
RFCs: Undefined variable error promotion · Undefined property error promotion
7. Removal of Deprecated Features
Any features deprecated in PHP 8.1-8.4 will be removed in PHP 9.0. This means updating legacy code is critical. Examples include:
- Old-style constructors (PHP 5.x style class constructors are long gone).
- GMP and ext-specific deprecations (e.g. certain extensions phased out).
- Other array/string behavior like the autovivification and string interpolation above.
The exact list comes from the RFCs for PHP 8.1, 8.2, 8.3, and 8.4 deprecations. In practice, any deprecation warning you see on PHP 8.3 now must be resolved before upgrading to 9.0. This cleanup keeps PHP modern but means breaking changes for older code. All deprecated functions, dynamic properties (if triggered), and legacy behavior will finally disappear.
RFC references: Deprecations for PHP 8.1 · Deprecations for PHP 8.2 · Deprecations for PHP 8.3 · Deprecations for PHP 8.4 · Deprecations for PHP 8.5 · Deprecations for PHP 8.6
8. Removal of Partially Supported Callables
Some callable formats have historically been accepted by functions like call_user_func() and by is_callable(), but were never fully supported by the $callable() invocation syntax. PHP 9.0 is planned to remove support for these “partially supported callables,” such as:
-
"self::method","parent::method","static::method" -
["self", "method"],["parent", "method"],["static", "method"]
Code that relies on these patterns will need to switch to fully supported callables (e.g. Foo::class . "::method", [Foo::class, "method"], or [new Foo(), "method"]).
RFC: Deprecate partially supported callables
9. Stricter Explicit Casts (No More “Fuzzy” Casts)
PHP’s explicit casts have historically allowed conversions that silently discard information (for example, turning "123abc" into 123). A newer proposal tightens this up by deprecating fuzzy casts in PHP 8.6 and making them throw TypeError in PHP 9.0.
Examples of the behavior targeted by the RFC:
// Partial string conversions (currently succeed by discarding trailing data)(int) "123abc"; // PHP 9.0: TypeError(float) "12.5foo"; // PHP 9.0: TypeError // Scalar-to-object casts (currently create a stdClass wrapper)(object) 42; // PHP 9.0: TypeError(object) "hello"; // PHP 9.0: TypeError
The goal is to align explicit cast behavior with the validation rules already used for typed parameters in non-strict mode.
RFC: Deprecate fuzzy and null casts
10. Implicit Bool-to-String Coercion Becomes a TypeError
Implicitly converting booleans to strings is being treated as a likely-bug pattern (false becomes '', true becomes '1'). The proposal is to emit E_DEPRECATED first and then raise it to a TypeError in PHP 9.0.
For example:
$flag = false;echo "Value: " . $flag; // PHP 9.0: TypeError (after deprecation period)
RFC: Deprecate boolean to string coercion
RFC: Make constructors and destructors return void
11. PHP 9.0 Drops 32-bit Builds
There is an active proposal to deprecate 32-bit support in the next PHP 8.x release and fully remove 32-bit builds in PHP 9.0. That means PHP 9.0 would no longer be buildable or runnable on 32-bit environments.
This is primarily motivated by platform trends and by long-standing 32-bit limitations (e.g., 2GB-ish limits and timestamp range issues).
RFC: Drop 32-bit Builds
12. Enum Introspection Cleanup (get_declared_enums() and class_exists() semantics)
A proposal adds a new get_declared_enums() function and tightens the meaning of “class” in reflection-style helpers:
-
class_exists()would be deprecated for enums in PHP 8.x and returnfalsefor enums in PHP 9.0. -
get_declared_classes()would stop returning enums in PHP 9.0.
enum Status { case Draft; } var_dump(enum_exists(Status::class)); // truevar_dump(class_exists(Status::class)); // PHP 9.0: false
RFC: Add get_declared_enums() function
13. Dynamic Properties Become Errors (Unless Explicitly Allowed)
In PHP, assigning to an undeclared property has historically created a dynamic property silently. This is now on a removal path: it was deprecated in PHP 8.2, and in PHP 9.0 it will throw an Error unless the class explicitly opts in.
class User { public string $name;} $user = new User;$user->nane = "typo"; // PHP 8.2: deprecation, PHP 9.0: Error
To keep intentional dynamic properties, PHP introduces #[AllowDynamicProperties] (and stdClass continues to allow them). Otherwise, declare the property, use __get()/__set(), or store external data in a WeakMap.
RFC: Deprecate dynamic properties
14. null to Non-Nullable Internal Scalar Arguments Throws TypeError
Historically, many internal functions in PHP would accept null for non-nullable scalar parameters in weak mode and silently coerce it (often to "", 0, or false). This behavior was deprecated in PHP 8.1 and becomes a TypeError in PHP 9.0, matching userland function behavior.
// Example behavior change:strlen(null); // PHP 8.1+: E_DEPRECATED, PHP 9.0: TypeError
The practical fix is to explicitly handle null before calling the function (or supply a default), rather than relying on implicit coercion.
RFC: Deprecate passing null to non-nullable arguments of internal functions
15. Removal of utf8_encode() and utf8_decode()
In PHP 9.0, utf8_encode() and utf8_decode() are removed. Codebases that still use them should migrate to supported encoding conversion APIs (the RFC highlights mb_convert_encoding() as the primary replacement, with UConverter::transcode() and iconv() as alternatives).
RFC: Remove utf8_encode and utf8_decode
16. Removal of GET/POST Session IDs, use_trans_sid, and the SID Constant
PHP’s legacy ability to propagate session IDs via GET/POST parameters (and automatically rewrite URLs via use_trans_sid) is on a removal track. The related INI settings and the SID constant are deprecated (targeted in PHP 8.4) and are intended to be removed in PHP 9.0.
This pushes session handling firmly toward cookie-based sessions (or explicit, application-level fallbacks when cookies can’t be used).
RFC: Deprecate GET/POST sessions
17. Fuzzy Scalar Casts Become TypeError (Proposal)
A newer proposal (currently under discussion) targets “fuzzy” casts—cases where explicit casts discard information (like partially parsing numeric strings) or create arbitrary structures (like casting scalars to (object)). The RFC proposes deprecations in PHP 8.6 and converting these cases into TypeError in PHP 9.0.
Examples of affected patterns include:
(int) "123abc"; // currently truncates to 123(float) "12.5foo"; // currently truncates to 12.5(object) 42; // currently produces stdClass with a scalar property
If accepted, this would further reduce “surprising” conversions and align casts with the validation rules already used for weak-mode typed parameters.
RFC: Deprecate Fuzzy Scalar Casts
How to Prepare and Migrate
Given these changes, PHP developers should start preparing now. Key recommendations include:
-
Enable strict error reporting. Run your code on PHP 8.3+ with
error_reporting(E_ALL)and fix every warning and notice. All deprecation warnings (e.g. old constructors, array/string quirks) should be addressed immediately. -
Refactor for type predictability. Avoid relying on implicit type conversions. For example, don’t depend on
falsemagically becoming an array. Initialize variables explicitly, and prefer type-safe code. -
Catch unserialization failures. Audit any calls to
unserialize()and wrap them intry/catchforUnserializationFailedException. Remove use ofSerializableif possible, as it will be phased out. - Follow RFC discussions. Stay active in PHP internals and community channels. The language continues to evolve, and being aware of accepted RFCs (via wiki.php.net/rfc) helps you know what’s coming.
- Test on pre-release versions. When PHP 9.0 alpha/betas appear, run your test suites and applications immediately. Catching incompatibilities early is far easier than after release.
- Monitor frameworks and libraries. Update to the latest versions of frameworks (Laravel, Symfony, etc.) that support PHP 9.0 as they become available. Library authors will likely release compatibility updates once 9.0 stabilizes.
Following these steps ensures a smoother upgrade path. Notably, sources emphasize fixing all deprecation warnings now and using explicit error handling so that PHP 9.0’s strictness becomes a feature, not a surprise.
Impact on the PHP Ecosystem
The PHP community and major sub-communities (Symfony, Laravel, WordPress, etc.) will need to adapt to PHP 9.0’s changes. None of our sources explicitly detail framework-specific updates, but we can extrapolate:
- Modern frameworks (Laravel, Symfony, etc.) typically target the latest PHP versions. They are likely already writing code that assumes strict types and explicit handling. These frameworks will probably embrace PHP 9.0 quickly updating internal code to remove deprecated features and leveraging new functions/APIs.
- WordPress is more conservative, supporting many older PHP releases for backwards compatibility. As such, the WordPress core team will likely take time to prepare. We can expect WordPress 7.0 (or another major release) to raise its minimum PHP requirement. Plugins and themes will need testing: any reliance on dynamic properties or autovivification must be fixed.
- PHP-FIG and Community Standards: PSR standards and shared libraries may be updated to reflect PHP 9.0 practices.
- Education and Adoption: The community will produce guides (like this one) and migration tools (like Rector sets) to help projects upgrade.
Conclusion
PHP 9.0 promises to be a cleaner, more predictable language than ever before. Its planned changes predictable operators, exception-based errors, streamlined syntax, and removal of legacy behavior may introduce breaking changes, but they ultimately strengthen PHP for future development. By taking action now (fixing deprecations, refactoring code, engaging with RFCs), developers can ensure a smooth transition. The end result will be PHP codebases that fail fast on genuine errors, leading to more robust web applications. As one source summarizes: “PHP 9.0 is shaping up to be a release that prioritizes predictability, stricter error handling, and cleaner syntax,” making the language more modern and developer-friendly.
Stay Updated.
I'll you email you as soon as new, fresh content is published.