Modern syntax
PHP 8 changed the language a lot: short and safe ways appeared to write what used to take several lines. These constructs show up in any modern code and framework.
The ?-> operator
A regular arrow causes an error when the left side is null. The ?-> operator stops the chain in that case and returns null:
<?php
class Address
{
public function __construct(public string $city) {}
}
class User
{
public function __construct(public ?Address $address = null) {}
}
$withAddress = new User(new Address('London'));
$withoutAddress = new User();
echo $withAddress->address?->city ?? 'no city', "\n"; // London
echo $withoutAddress->address?->city ?? 'no city'; // no cityDestructuring
An array can be spread into variables in one line:
<?php
[$first, $second] = ['tea', 'coffee'];
['name' => $name, 'age' => $age] = ['name' => 'Anna', 'age' => 25];
echo $first, ' ', $second, ' ', $name, ' ', $age; // tea coffee Anna 25Values are swapped the same way: [$a, $b] = [$b, $a]. In a foreach loop it removes the need to access by key:
<?php
$points = [[1, 2], [3, 4]];
foreach ($points as [$x, $y]) {
echo $x + $y, ' ';
}The spread operator
Three dots insert the elements of one array into another:
<?php
$defaults = ['theme' => 'light', 'size' => 14];
$custom = ['size' => 16];
$settings = [...$defaults, ...$custom];
echo json_encode($settings); // {"theme":"light","size":16}When string keys clash, the value that comes later wins.
Default assignment
The ??= operator assigns a value only if the variable is not set or is null:
<?php
$options = ['theme' => 'dark'];
$options['theme'] ??= 'light';
$options['size'] ??= 14;
echo json_encode($options); // {"theme":"dark","size":14}Immutable objects
A class with the word readonly makes every property read-only. To "change" an object, a new one is created:
<?php
readonly class Money
{
public function __construct(public int $amount, public string $currency) {}
public function add(int $value): static
{
return new static($this->amount + $value, $this->currency);
}
}
$price = new Money(250, 'USD');
$total = $price->add(100);
echo $price->amount, ' ', $total->amount; // 250 350A reference to a function
The form with three dots in parentheses turns a function or a method into a value:
<?php
$upper = strtoupper(...);
echo implode(', ', array_map($upper, ['php', 'js'])); // PHP, JSAttributes
An attribute is a label in the code that frameworks and tools read. It is written before a class, a method or a parameter in #[ ]:
<?php
#[Attribute]
class Route
{
public function __construct(public string $path) {}
}
class PostController
{
#[Route('/posts')]
public function index(): string
{
return 'List of posts';
}
}
$method = new ReflectionMethod(PostController::class, 'index');
$route = $method->getAttributes(Route::class)[0]->newInstance();
echo $route->path; // /postsAn attribute does nothing by itself — it only stores information that someone reads later.
Common mistake
New syntax requires a new PHP version on the server. readonly classes appeared in 8.2, enumerations and readonly properties in 8.1, named arguments and match in 8.0. Before using a construct, check the version with php -v and state it in composer.json.