12 вопросов
public int $age;fn($x) => $x * 2[...$arr1, ...$arr2]$x ??= 'default'1_000_000str_contains(haystack: $s, needle: 'x')int|string$user?->getAddress()?->getCity()#[Route('/api')]$value ?? throw new Exception()A&Bpublic readonly string $namestrlen(...)(A&B)|C (Disjunctive Normal Form)const string VERSION = '1.0'public private(set) string $namenew User->getName()// Объявление атрибута
#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
class Route {
public function __construct(
public string $path,
public string $method = 'GET',
) {}
}
// Использование
class UserController {
#[Route('/users', method: 'GET')]
#[Route('/users/list', method: 'GET')]
public function list(): Response { /* ... */ }
}
// Чтение через Reflection
$ref = new ReflectionMethod(UserController::class, 'list');
$attrs = $ref->getAttributes(Route::class);
foreach ($attrs as $attr) {
$route = $attr->newInstance();
echo "$route->method $route->path\n";
}Атрибуты заменяют docblock-аннотации (@Route). Нативная поддержка PHP, проверка типов, IDE-подсказки.
// match - строгое сравнение (===), возвращает значение
$result = match($status) {
'active' => 'Активен',
'banned', 'blocked' => 'Заблокирован', // несколько значений
default => 'Неизвестно',
};
// Без аргумента - как if/elseif
$category = match(true) {
$age < 18 => 'child',
$age < 65 => 'adult',
default => 'senior',
};Отличия от switch: строгое сравнение (===), нет fallthrough, возвращает значение, UnhandledMatchError если нет совпадения (без default).
// ?? (Null coalescing) - значение по умолчанию если null
$name = $user->name ?? 'Anonymous';
$config = $data['key'] ?? $fallback ?? 'default';
// ??= (Null coalescing assignment, PHP 7.4)
$options['timeout'] ??= 30; // установить если null
// ?-> (Nullsafe operator, PHP 8.0) - цепочка вызовов с проверкой null
$city = $user?->getAddress()?->getCity()?->getName();
// Вместо:
// $city = $user !== null && $user->getAddress() !== null && ...
// ?-> возвращает null при первом null в цепочке
// Нельзя использовать для записи: $user?->name = 'x'; // Error// Intersection type (PHP 8.1): объект должен реализовать ВСЕ типы
function process(Countable&Iterator $collection): void {
echo count($collection);
foreach ($collection as $item) { /* ... */ }
}
// DNF types (PHP 8.2): комбинация union и intersection
function handle((Countable&Iterator)|null $data): void { /* ... */ }
// Практический пример
interface Cacheable {}
interface Serializable {}
function store(Cacheable&Serializable $item): void {
// $item гарантированно реализует оба интерфейса
}Intersection types полезны когда нужно требовать реализацию нескольких интерфейсов без создания промежуточного интерфейса.
// Fiber (PHP 8.1) - кооперативная многозадачность
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('первая пауза');
echo "Получил: $value\n";
Fiber::suspend('вторая пауза');
});
$result = $fiber->start(); // "первая пауза"
$result = $fiber->resume('данные'); // "Получил: данные", "вторая пауза"
$fiber->resume();Fibers - низкоуровневый механизм для асинхронных фреймворков (ReactPHP, Amp, Revolt). Не для прямого использования в приложениях. Позволяют писать асинхронный код в синхронном стиле.
По состоянию на 2025-2026:
Каждая версия получает 2 года активной поддержки + 1 год security-only. Рекомендация: использовать последнюю стабильную версию (8.4).