What's New in PHP 8
PHP 8 introduced several features that make code shorter, safer, and easier to read. This page
walks through the five most useful additions: the match expression, named arguments,
the nullsafe operator (?->), constructor property promotion, and
union types.
1) The match Expression
match is like a stricter switch that returns a value. It uses
strict comparison (===) internally, has no fallthrough between arms, and
throws an UnhandledMatchError if nothing matches and there is no default.
<?php
$status = 200;
$label = match ($status) {
200, 201 => 'Success',
404 => 'Not Found',
500 => 'Server Error',
default => 'Unknown',
};
echo $label; // Success
?>
switch | match |
|---|---|
Loose comparison (==) | Strict comparison (===) |
Falls through without break | No fallthrough — each arm is isolated |
| A statement (does not return a value) | An expression (returns a value directly) |
| Missing case is silently skipped | Missing case + no default throws UnhandledMatchError |
2) Named Arguments
Named arguments let you pass values by parameter name instead of position, making calls with several parameters self-documenting and letting you skip optional ones in any order.
<?php
function myFunc(string $name, int $age = 18, string $country = 'IN') {
echo "{$name}, {$age}, {$country}";
}
// Positional (old way)
myFunc('Sonu', 25);
// Named arguments (PHP 8) - order doesn't matter, intent is clear
myFunc(name: 'Sonu', age: 25);
myFunc(country: 'US', name: 'Amit'); // skips $age, uses its default
?>
3) The Nullsafe Operator (?->)
When chaining property or method access on something that might be null, the nullsafe
operator short-circuits the whole chain to null instead of throwing a fatal error.
<?php
// Before PHP 8: verbose null checks at every step
$city = null;
if ($user !== null && $user->address !== null) {
$city = $user->address->city;
}
// PHP 8: nullsafe operator - short-circuits to null, no fatal error
$city = $user?->address?->city;
?>
4) Constructor Property Promotion
Promoting constructor parameters directly into typed class properties removes the repetitive boilerplate of declaring a property and then assigning it inside the constructor body.
<?php
// Before PHP 8
class Product {
private string $name;
private float $price;
public function __construct(string $name, float $price) {
$this->name = $name;
$this->price = $price;
}
}
// PHP 8: constructor property promotion - same result, far less code
class Product {
public function __construct(
private string $name,
private float $price
) {}
}
?>
5) Union Types
A parameter, return, or property type can now be declared as one of several possible types using
the | separator, instead of falling back to no type at all.
<?php
// $x may be an int OR a string
function formatId(int|string $x): string {
return 'ID-' . $x;
}
echo formatId(42); // ID-42
echo formatId('A9'); // ID-A9
?>
| Feature | What it solves |
|---|---|
match | Shorter, safer branching that returns a value with strict comparison |
| Named arguments | Self-documenting calls; skip optional parameters freely |
Nullsafe ?-> | Fewer nested null checks when chaining calls/properties |
| Constructor promotion | Less boilerplate for simple data-holding classes |
| Union types | Accurate type hints when a value can legitimately be more than one type |
switch, positional arguments, chained isset() checks, and normal
constructors — then adopt these PHP 8 features once your hosting environment is upgraded.