Which headline language features did each PHP release from 8.0 to 8.5 introduce?
answer
- 8.0 the big line: JIT, match, attributes
- 8.1 enums, readonly, fibers
- 8.3 typed class constants, #[\Override]
- 8.4 property hooks, asymmetric visibility
- 8.5 pipe operator, clone-with
basics
~20 s8.0: named arguments, attributes, union types, match, nullsafe, promotion, JIT. 8.1: enums, readonly, fibers, first-class callables. 8.2: readonly classes, DNF types. 8.3: typed class constants, #[\Override]. 8.4: property hooks, asymmetric visibility. 8.5: pipe operator, clone-with.
solid answer
~30 s**8.0** was the big release: named arguments, attributes, constructor property promotion, union types, `match`, the nullsafe operator `?->`, `mixed`, `str_contains()` and a JIT in OPcache. **8.1** added enums, readonly properties, fibers, first-class callable syntax `f(...)`, intersection types and `never`. **8.2** added readonly classes, DNF types, standalone `null`/`false`/`true` types and the Random extension. **8.3** added typed class constants, `#[\Override]`, dynamic class-constant fetch and `json_validate()`. **8.4** added property hooks, asymmetric visibility, lazy objects, `new Foo()->bar()` without parentheses, `array_find()` and friends, and the `#[\Deprecated]` attribute. **8.5** added the pipe operator `|>`, clone-with, `#[\NoDiscard]`, `array_first()`/`array_last()` and the URI extension.
code
php · 20 lines<?php
declare(strict_types=1);
enum Status: string { case Draft = 'draft'; case Sent = 'sent'; } // 8.1
final class Invoice
{
public function __construct(
public readonly string $number, // promotion 8.0, readonly 8.1
public private(set) Status $status, // asymmetric visibility 8.4
) {}
}
$invoice = new Invoice(number: 'INV-1', status: Status::Draft); // named args 8.0
$slug = ' Invoice Draft '
|> trim(...) // pipe 8.5, first-class callable 8.1
|> strtolower(...);
$first = array_first(['a', 'b']); // 8.5go deeper
Recall a handful of anchors: match and named arguments in 8.0, enums and readonly in 8.1, property hooks in 8.4, the pipe operator in 8.5.
Place most headline features on the right release and pair each minor with the deprecation it brought, such as dynamic properties in 8.2.
Use the map to plan: know which features you can adopt at your minimum supported version and which deprecations block the next upgrade.
Decide when a codebase may adopt a new release's features, balancing the gain against every deployment target and shared library that must move to that version first.
## Why this question comes up Interviewers ask "which version added X" to see whether a candidate has written current PHP or only read about it. You are not expected to recite every changelog line; you are expected to place the headline features on the right release and to know that **8.0 is the dividing line** between legacy and modern PHP. Each feature's mechanics are a separate topic; this is the map. ## The release-by-release map | Release | Headline language features | Notable functions and APIs | |---|---|---| | **8.0** | named arguments, attributes `#[...]`, constructor property promotion, union types, `match`, nullsafe `?->`, `mixed`, `static` return type, `throw` as an expression | `str_contains()`, `str_starts_with()`, `str_ends_with()`, `WeakMap`, `ValueError`, the `Stringable` interface, a JIT in OPcache | | **8.1** | enums, readonly properties, fibers, first-class callable syntax `strlen(...)`, pure intersection types, `never`, `new` in initializers, `0o` octal prefix | `array_is_list()` | | **8.2** | readonly classes, DNF types, standalone `null`, `false` and `true` types, constants in traits | the Random extension, `#[\SensitiveParameter]` | | **8.3** | typed class constants, `#[\Override]`, dynamic class-constant fetch `C::{$name}`, readonly properties re-initialisable during cloning | `json_validate()`, `mb_str_pad()`, `str_increment()` | | **8.4** | property hooks, asymmetric visibility such as `public private(set)`, lazy objects, `new Foo()->method()` without wrapping parentheses | `array_find()`, `array_any()`, `array_all()`, `BcMath\Number`, `Dom\HTMLDocument`, PDO driver subclasses such as `Pdo\Mysql`, `#[\Deprecated]` | | **8.5** | the pipe operator `\|>`, clone-with (`clone($obj, [...])`), `#[\NoDiscard]` with a `(void)` cast, closures in constant expressions | `array_first()`, `array_last()`, the URI extension (`Uri\Rfc3986\Uri`, `Uri\WhatWg\Url`) | ## 8.0: the dividing line PHP 8.0 was a **major** release, so it combined new features with the largest set of behaviour changes in the 8.x line: - Comparing a number with a **non-numeric** string now compares them as strings, so `0 == "foo"` became `false`. - Many engine warnings became `Error` exceptions, and internal functions throw `TypeError` or `ValueError` on bad arguments. - PDO's default error mode became exceptions. - `create_function()`, `each()` and `__autoload()` were removed. That is why teams speak of "before 8" and "after 8" even though every later minor also changed things. ## Minor releases still change behaviour The features arrive with deprecations that matter for upgrades: - **8.1** deprecated passing `null` to non-nullable parameters of built-in functions, and made mysqli throw by default. - **8.2** deprecated **dynamic properties** (unless the class has `#[\AllowDynamicProperties]`) and `"${var}"` string interpolation. - **8.4** deprecated **implicitly nullable** parameter types (`Foo $x = null`) and removed the `E_STRICT` level. - **8.5** deprecated the backtick operator, the non-canonical casts such as `(integer)`, and ending a `case` with `;`. ## Adopting a feature: syntax versus functions Knowing the release of a feature matters most when code must run on more than one version: - **Syntax features** such as enums, `match`, property hooks or `|>` are **parse errors** on older versions. The whole file fails to compile, so they can be used only once every runtime that loads the file is on the new release. - **New functions** such as `str_contains()` or `array_first()` can be **polyfilled**: define the function only when `function_exists()` says it is missing. A library can therefore use them before its minimum PHP version reaches the release that added them. - **New classes and attributes** sit in between: an attribute naming a class that does not exist is not an error until something reads it through reflection, while a missing class used with `new` fails at runtime. ## How to answer well A strong answer does three things: 1. Anchors the big items correctly: enums and readonly in 8.1, property hooks in 8.4, the pipe operator in 8.5. 2. Mentions that each minor also brought deprecations, so "which version added X" and "which version broke Y" go together. 3. Knows where to check: the manual's **migration guides** ("Migrating from PHP 8.4.x to PHP 8.5.x" and so on) list new features, new functions, backward-incompatible changes and deprecations per release. Common slips are putting enums in 8.0, putting readonly classes in 8.1 (readonly *properties* are 8.1, readonly *classes* 8.2), and describing an 8.6 feature as available: 8.6 is still in pre-release, and **8.5** is the current stable line.
- Readonly properties and readonly classes: which version added which?Readonly **properties** arrived in PHP 8.1: a property declared `readonly` can be initialised once from inside the class scope. Readonly **classes** arrived in 8.2: marking the class `readonly` makes every declared property readonly. 8.3 then allowed readonly properties to be re-initialised during cloning, and 8.5's clone-with lets you pass new values to `clone()`.
- Where do you look up exactly what changed between two PHP versions?In the PHP manual's migration appendices, one per minor, such as "Migrating from PHP 8.4.x to PHP 8.5.x". Each has sections for new features, new classes, new functions, backward-incompatible changes, deprecated features and other changes. The php-src `UPGRADING` file in the release tag carries the same information for the latest version.
saying these in an interview costs you the question
- Enums have been part of PHP since 8.0.
- Property hooks and the pipe operator both arrived in PHP 8.4.
- Minor releases only add features and never deprecate anything.
- Readonly classes came in 8.1, together with readonly properties.
- PHP 8.6 is the current stable release.