Symfony 8.0 — текущая стабильная мажорная версия фреймворка. На май 2026 актуальный патч — 8.0.11 (вышел 13 мая 2026). Ветка следует обычному ритму: минорные релизы дважды в год (май и ноябрь), мажорные — раз в два года. Параллельно поддерживается 7.4 LTS (long-term support — долгосрочная поддержка), которая получает исправления дольше.
Ниже разобраны не «общие отличия от 7.4» (это отдельная тема), а конкретные компоненты и механизмы, которые делают ветку 8.0 заметно отличной от привычной 7.x. Все английские термины и примеры сопровождаются переводом.
Требование PHP 8.4 и нативные lazy-объекты
Symfony 8.0 требует PHP 8.4 как минимум. Главная причина — не косметика, а то, что фреймворк теперь опирается на возможности самого языка, а не на собственные обходные решения.
Раньше «ленивые» сервисы реализовывались через трейты LazyGhostTrait и LazyProxyTrait (trait — примесь, переиспользуемый набор методов). В 8.0 эти трейты удалены: вместо них используется нативная фича PHP 8.4 — lazy objects (ленивые объекты).
Lazy object (ленивый объект) — это объект, который создаётся «пустым» и инициализирует себя сам только при первом обращении к его свойствам или методам. Это экономит память и время: тяжёлый сервис не строится, пока реально не понадобился.
Важное следствие: поскольку механизм теперь нативный, ленивыми могут быть даже final и readonly классы (final — нельзя наследовать; readonly — свойства только для чтения), что раньше было ограничением прокси-подхода.
# config/services.yaml
services:
App\Service\HeavyReportBuilder:
lazy: true # ленивая инициализация через нативный механизм PHP 8.4
<?php
declare(strict_types=1);
namespace App\Service;
// final + readonly теперь совместимы с lazy-инициализацией
final readonly class HeavyReportBuilder
{
public function __construct(
private ExpensivePdfRenderer $renderer, // создастся только при первом обращении
) {
}
}
ObjectMapper: маппинг объектов без ручного кода
ObjectMapper (маппер объектов) — компонент, который превращает один объект в другой по правилам, описанным атрибутами. Он появился в ветке 7.3, стабилизировался и в 8.0 уже воспринимается как штатный инструмент.
Типичная боль: перекладывать поля из DTO (Data Transfer Object — объект передачи данных) в сущность (entity) и обратно вручную. ObjectMapper убирает этот шаблонный код (boilerplate — однообразный повторяющийся код).
<?php
declare(strict_types=1);
namespace App\DTO;
use App\Entity\User;
use Symfony\Component\ObjectMapper\Attribute\Map;
// #[Map(target: ...)] говорит: этот DTO маппится в сущность User
#[Map(target: User::class)]
final class UserInput
{
public string $email = '';
// source/target имя поля отличается — указываем явно
#[Map(target: 'fullName')]
public string $name = '';
// transform применяет функцию перед записью в целевой объект
#[Map(target: 'roles', transform: 'str_getcsv')]
public string $rolesCsv = 'ROLE_USER';
}
<?php
declare(strict_types=1);
namespace App\Controller;
use App\DTO\UserInput;
use App\Entity\User;
use Symfony\Component\ObjectMapper\ObjectMapperInterface;
final class RegistrationController
{
public function __construct(
private readonly ObjectMapperInterface $objectMapper,
) {
}
public function register(UserInput $input): void
{
// map() сам разложит поля DTO по сущности согласно атрибутам #[Map]
$user = $this->objectMapper->map($input, User::class);
// дальше — сохранение через репозиторий
}
}
Опция transform (преобразование) работает не только на источнике, но и на целевом классе. Это удобно, когда источник вообще не имеет своего класса — например, данные из JSON или CSV — и логику преобразования хочется держать рядом с целевым объектом.
JsonStreamer: потоковая сериализация JSON
JsonStreamer (потоковый JSON-сериализатор) — новый высокопроизводительный компонент, кодирующий PHP-данные в JSON и декодирующий обратно потоково (streaming — потоковая обработка), а не целиком в памяти.
Зачем он нужен: классический Serializer держит весь результат в памяти. На больших объёмах (десятки тысяч записей, экспорт, выгрузки API) это дорого. JsonStreamer пишет/читает по частям, поэтому потребление памяти остаётся низким даже на огромных payload (payload — полезная нагрузка, тело запроса/ответа).
Для оптимизации при чтении JsonStreamer создаёт ghost objects (объекты-призраки) — лёгкие заглушки, которые откладывают реальное создание объекта до момента, когда данные действительно понадобятся.
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Dto\ProductRow;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\JsonStreamer\StreamWriterInterface;
use Symfony\Component\TypeInfo\Type;
final class ExportController
{
public function __construct(
// StreamWriter пишет JSON потоково
private readonly StreamWriterInterface $jsonStreamWriter,
) {
}
public function export(iterable $products): StreamedResponse
{
return new StreamedResponse(function () use ($products): void {
// отдаём список объектов, не загружая весь JSON в память
foreach ($this->jsonStreamWriter->write(
$products,
Type::list(Type::object(ProductRow::class)),
) as $chunk) {
echo $chunk; // отдаём по кускам (chunk — порция данных)
}
});
}
}
TypeInfo: единый источник информации о типах
TypeInfo (информация о типах) — компонент, извлекающий PHP-типы из свойств, методов и функций в едином формате. Раньше каждый компонент (Serializer, Validator, PropertyInfo) трактовал типы по-своему; TypeInfo даёт общий «язык» для описания типов, на который опираются JsonStreamer, ObjectMapper и сериализация.
<?php
declare(strict_types=1);
use Symfony\Component\TypeInfo\Type;
// Описание типов в едином виде
$listOfInts = Type::list(Type::int()); // list<int> — список целых
$nullableStr = Type::nullable(Type::string()); // ?string — строка или null
$collection = Type::collection(
Type::object(\ArrayObject::class),
Type::string(), // тип значений
Type::int(), // тип ключей
);
Прямой работы с этим API в повседневном коде немного, но именно он стоит за тем, что новые компоненты понимают друг друга и аккуратно сериализуют коллекции и вложенные объекты.
Встроенный HTML5-парсер
Ещё одна причина перехода на PHP 8.4 — нативный HTML5 Parser (парсер HTML5), встроенный в язык. Компоненты Symfony, работающие с разметкой (DomCrawler, HtmlSanitizer), теперь опираются на него.
HtmlSanitizer (очиститель HTML) — инструмент безопасной очистки пользовательского HTML от потенциально опасных тегов и атрибутов (защита от XSS — cross-site scripting, межсайтовый скриптинг). Благодаря нативному парсеру разбор разметки соответствует современному стандарту HTML5 и работает точнее.
<?php
declare(strict_types=1);
use Symfony\Component\HtmlSanitizer\HtmlSanitizer;
use Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig;
$config = (new HtmlSanitizerConfig())
->allowSafeElements() // разрешить только безопасные элементы
->allowElement('a', ['href']); // плюс ссылки с атрибутом href
$sanitizer = new HtmlSanitizer($config);
// На выходе — очищенный HTML без <script> и опасных атрибутов
$safe = $sanitizer->sanitize('<a href="/x" onclick="evil()">click</a><script>steal()</script>');
Облегчение кодовой базы: удаление устаревшего
В 8.0 убраны все возможности, помеченные как deprecated (устаревшие) в ветке 7.x. Это убрало порядка 13 тысяч строк кода — фреймворк стал легче и предсказуемее. Среди удалённого, помимо упомянутых lazy-трейтов, — автоматический маппинг сущностей Doctrine (Doctrine entity auto-mapping), который теперь надо настраивать явно.
Практический вывод: перед обновлением на 8.0 сначала доводят проект на 7.4 до состояния «ноль deprecation warnings» (предупреждений об устаревании), и только потом поднимают мажорную версию.
# Прогнать тесты так, чтобы любой deprecation падал ошибкой
SYMFONY_DEPRECATIONS_HELPER="max[total]=0" php bin/phpunit
Итоги
- Symfony 8.0 — актуальная стабильная ветка (на май 2026 — патч 8.0.11); 7.4 остаётся LTS.
- Минимум PHP 8.4: фреймворк использует нативные lazy objects и HTML5 Parser вместо собственных обходов.
- ObjectMapper убирает ручной маппинг DTO ↔ сущность через атрибуты
#[Map]с опциейtransform. - JsonStreamer даёт потоковую сериализацию JSON с низким расходом памяти на больших объёмах.
- TypeInfo — единый формат типов, на который опираются новые компоненты.
- HtmlSanitizer и DomCrawler работают на нативном HTML5-парсере PHP 8.4.
- Удалены все deprecated из 7.x (~13k строк) — миграцию начинают с устранения предупреждений на 7.4.