Урок 01

Что изменилось в PHP 8+

Зачем эта версия

PHP 8.0 (ноябрь 2020) — крупнейшее обновление языка за десятилетие. Затем 8.1 (2021), 8.2 (2022), 8.3 (2023), 8.4 (2024).

Главное: JIT-компиляция, современный синтаксис, строгая типизация, много удобных конструкций.

JIT-компиляция

Just-In-Time — компилирует байт-код в машинный код во время выполнения.

Что даёт:

  • Ускорение в вычислительных задачах в 2–5 раз.
  • Математика, обработка изображений, ML — выигрывают больше всего.
  • Обычный веб — ускорение меньше, узкое место обычно БД.

Как включить:

opcache.jit_buffer_size = 128M
opcache.jit = tracing

По умолчанию выключен, для веба не обязателен.

Новый синтаксис

Named arguments

// До 8.0
htmlspecialchars($text, ENT_QUOTES, 'UTF-8', true);

// PHP 8.0+
htmlspecialchars($text, encoding: 'UTF-8');

Match expression

$status = match ($code) {
    200, 201, 204 => 'Успех',
    400, 422 => 'Ошибка клиента',
    500, 502 => 'Ошибка сервера',
    default => 'Другое',
};

Строгое сравнение, возвращает значение, без break.

Nullsafe operator

$city = $user?->address?->city;

Constructor property promotion

class Point
{
    public function __construct(
        public readonly int $x,
        public readonly int $y,
    ) {}
}

Union types

function formatId(int|string $id): string
{
    return (string) $id;
}

Enums

enum Status: string
{
    case Active = 'active';
    case Pending = 'pending';
}

Readonly properties

class User
{
    public function __construct(
        public readonly string $email,
    ) {}
}

Атрибуты

#[Route('/api/users', methods: ['GET'])]
class UsersController { }

Что нового в 8.1

  • Enum (полноценные).
  • never — тип возврата.
  • Readonly properties.
  • First-class callable syntax — $fn = strlen(...).
  • Fibers — примитивы асинхронности.
  • Pure intersection types — A&B.
  • array_is_list().
  • new в инициализаторах — new в параметрах по умолчанию.

Что нового в 8.2

  • Readonly classes — readonly class Foo.
  • Disjunctive Normal Form types — (A&B)|C.
  • null, false, true как отдельные типы.
  • Устаревание динамических свойств — теперь warning.
  • Константы в трейтах — теперь можно.

Что нового в 8.3

  • Typed class constants — const int MAX = 100.
  • json_validate() — проверка JSON без декодирования.
  • Анонимные readonly-классы.
  • Динамические обращения к константам класса — Foo::{$name}.
  • Улучшения #[Override].

Что нового в 8.4

  • Property hooks — геттеры/сеттеры на свойствах.
  • Асимметричная видимость — public private(set) string $x.
  • new без скобок — new Foo()->method().
  • #[\Deprecated] атрибут.
  • array_find, array_find_key, array_any, array_all.
  • Улучшенный mb_* для Unicode.

Строгая типизация

declare(strict_types=1) — с 7.0, но стал нормой в 8+.

<?php

declare(strict_types=1);

function sum(int $a, int $b): int
{
    return $a + $b;
}

sum('2', '3');   // TypeError
sum(2, 3);       // 5

Стандарт — включать в каждом файле.

Ошибки стали строже

PHP 8.0:

  • Неопределённые переменные — Warning (было Notice).
  • Неопределённые индексы массива — Warning.
  • Обращение к null — TypeError.
  • Некорректные строки при арифметике — TypeError.

Пример:

// PHP 7
$a = 'abc' + 1;   // 1 (с Notice)

// PHP 8
$a = 'abc' + 1;   // TypeError

Хорошо: баги ловятся раньше.

Производительность

ВерсияПрирост
7.02× к 5.6
7.4+10-25%
8.0+10-30%
8.1+5-15%
8.2+3-10%
8.3+2-5%
8.4+2-5%

Итого от 5.6 к 8.4 — в 3–5 раз быстрее.

Совместимость

Обратная совместимость — хорошая, но есть breaking changes:

  • Устаревшие функции удалены.
  • Изменения в неявных приведениях.
  • Изменения в стандартной библиотеке.

Для миграции:

  • PHPStan — статический анализ.
  • Rector — автоисправление.
  • Psalm — ещё один анализатор.

Экосистема

Современные фреймворки требуют PHP 8+:

  • Laravel 10+ — PHP 8.1+.
  • Laravel 11 — PHP 8.2+.
  • Symfony 7 — PHP 8.2+.
  • WordPress 6.x — PHP 7.4+.

Composer пакеты — большинство требует 8.1+.

Что использовать

В новых проектах:

  • PHP 8.3+ — стабильно.
  • PHP 8.4 — если готов к обновлениям.

Минимум для продакшена — 8.1 (EOL 8.0 — 2023).

Практика

<?php

declare(strict_types=1);

enum OrderStatus: string
{
    case Pending = 'pending';
    case Paid = 'paid';
    case Shipped = 'shipped';
    case Cancelled = 'cancelled';

    public function label(): string
    {
        return match ($this) {
            self::Pending => 'Ожидает',
            self::Paid => 'Оплачен',
            self::Shipped => 'Отправлен',
            self::Cancelled => 'Отменён',
        };
    }
}

final readonly class Order
{
    public function __construct(
        public int $id,
        public OrderStatus $status,
        public ?string $comment = null,
    ) {}
}

$order = new Order(id: 1, status: OrderStatus::Paid);

echo $order->status->label();   // Оплачен

Итог

  • PHP 8+ — современный язык.
  • JIT — для вычислений.
  • Match, enums, readonly, named args — норм.
  • Strict types — обязательно.
  • Ошибки строже — лови баги рано.
  • Минимум 8.1, лучше 8.3+.

Дальше — типизация: аргументы и возвращаемые значения.