Современный синтаксис
PHP 8 сильно изменил язык: появились короткие и безопасные способы записать то, что раньше занимало несколько строк. Эти конструкции встречаются в любом современном коде и фреймворках.
Оператор ?->
Обычная стрелка вызывает ошибку, если слева null. Оператор ?-> в этом случае останавливает цепочку и возвращает null:
<?php
class Address
{
public function __construct(public string $city) {}
}
class User
{
public function __construct(public ?Address $address = null) {}
}
$withAddress = new User(new Address('Казань'));
$withoutAddress = new User();
echo $withAddress->address?->city ?? 'город не указан', "\n"; // Казань
echo $withoutAddress->address?->city ?? 'город не указан'; // город не указанДеструктуризация
Массив можно разложить по переменным одной строкой:
<?php
[$first, $second] = ['чай', 'кофе'];
['name' => $name, 'age' => $age] = ['name' => 'Анна', 'age' => 25];
echo $first, ' ', $second, ' ', $name, ' ', $age; // чай кофе Анна 25Так же меняют значения местами: [$a, $b] = [$b, $a]. В цикле foreach это избавляет от обращений по ключу:
<?php
$points = [[1, 2], [3, 4]];
foreach ($points as [$x, $y]) {
echo $x + $y, ' ';
}Оператор распаковки
Три точки вставляют элементы одного массива в другой:
<?php
$defaults = ['theme' => 'light', 'size' => 14];
$custom = ['size' => 16];
$settings = [...$defaults, ...$custom];
echo json_encode($settings); // {"theme":"light","size":16}При совпадении строковых ключей побеждает значение, которое стоит позже.
Присваивание по умолчанию
Оператор ??= присваивает значение, только если переменная не задана или равна null:
<?php
$options = ['theme' => 'dark'];
$options['theme'] ??= 'light';
$options['size'] ??= 14;
echo json_encode($options); // {"theme":"dark","size":14}Неизменяемые объекты
Класс со словом readonly делает все свойства доступными только для чтения. Чтобы «изменить» объект, создают новый:
<?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, 'RUB');
$total = $price->add(100);
echo $price->amount, ' ', $total->amount; // 250 350Ссылка на функцию
Запись с тремя точками в скобках превращает функцию или метод в значение:
<?php
$upper = strtoupper(...);
echo implode(', ', array_map($upper, ['php', 'js'])); // PHP, JSАтрибуты
Атрибут — это метка в коде, которую читают фреймворки и инструменты. Его пишут перед классом, методом или параметром в #[ ]:
<?php
#[Attribute]
class Route
{
public function __construct(public string $path) {}
}
class PostController
{
#[Route('/posts')]
public function index(): string
{
return 'Список статей';
}
}
$method = new ReflectionMethod(PostController::class, 'index');
$route = $method->getAttributes(Route::class)[0]->newInstance();
echo $route->path; // /postsСам по себе атрибут ничего не делает — он лишь хранит сведения, которые кто-то потом прочитает.
Частая ошибка
Новый синтаксис требует новой версии PHP на сервере. readonly-классы появились в 8.2, перечисления и readonly-свойства — в 8.1, именованные аргументы и match — в 8.0. Прежде чем использовать конструкцию, проверьте версию командой php -v и укажите её в composer.json.