PHP долго был языком с динамической типизацией и репутацией «всё приведётся само». Начиная с PHP 7, а особенно с версий 8.0–8.3, система типов стала по-настоящему выразительной.
🔍 Что появилось и зачем
🔹 Union Types (8.0)
Тип может быть одним из нескольких:
function process(int|string $id): User|null {
// ...
}Раньше это документировали только в PHPDoc и надеялись на лучшее.
🔹 mixed, never, void
▪️ mixed — явно говорит "любой тип", в отличие от отсутствия типа
▪️ never — функция никогда не вернёт управление (бросает исключение или завершает процесс)
▪️ void — функция ничего не возвращает
function redirect(string $url): never {
header("Location: $url");
exit();
}🔹 Intersection Types (8.1)
Значение должно реализовывать все указанные интерфейсы одновременно:
function process(Serializable&Countable $data): void {
// ...
}Полезно при работе с коллекциями и DTO, которые соответствуют нескольким контрактам.
🔹 Enums (8.1)
Наконец-то нативные перечисления вместо констант в классах:
enum Status: string {
case Active = 'active';
case Inactive = 'inactive';
}
function setStatus(Status $status): void { ... }Теперь нельзя передать произвольную строку туда, где ожидается Status.
🔹 Readonly properties (8.1) и readonly классы (8.2)
class User {
public function __construct(
public readonly int $id,
public readonly string $name,
) {}
}В 8.2 можно пометить весь класс как readonly — все свойства автоматически становятся иммутабельными. Отлично подходит для Value Objects и DTO.
🔹 DNF Types — Disjunctive Normal Form (8.2)
Комбинация union и intersection:
function handle(Countable&Iterator|null $collection): void {
// ...
}Тип читается как: "реализует оба интерфейса, либо null".
🔹 typed class constants (8.3)
class Config {
const string VERSION = '1.0.0';
const int MAX_RETRIES = 3;
}До 8.3 константы классов не имели типов — теперь контракт полный.
⚠️ Нюансы
— declare(strict_types=1) обязателен, иначе PHP будет тихо приводить типы и "5" пройдёт там, где ожидается int
— Intersection types не работают с примитивами только с интерфейсами и классами
— readonly нельзя применить к static свойствам
— Enums не поддерживают наследование
Библиотека пхпшника