Symfony 7.4: Что нового
Представляем Symfony 7.4: отказ от XML-конфигурации, улучшенные voters, UUID v7 по умолчанию, кеширование HTTP-клиента, валидация видео и многое другое для эффективной разработки.
В ноябре 2025 года вышел долгожданный релиз Symfony 7.4, продолжающий традицию эволюционного развития фреймворка с сохранением обратной совместимости. Это обновление приносит десятки улучшений, направленных на повышение производительности, безопасности и удобства разработчиков.
В этой статье мы перечислим и разберем ключевые нововведения: отказ от устаревшего XML в конфигурации, новые возможности для безопасности (Voter), переход на современные UUID v7, встроенное кеширование HTTP-клиента по стандарту RFC 9111, мощное ограничение для валидации видеофайлов и многое другое.
Готовьтесь к плавному обновлению и новым инструментам для ваших проектов
Список нововведений
Устаревание XML-конфигурации: Чтобы упростить настройку приложений, Symfony 7.4 объявляет XML устаревшим форматом конфигурации.
Улучшения Security Voter: Добавлены новые функции Twig и возможность настраивать метаданные для механизма голосования безопасности.
Улучшения Uid: По умолчанию теперь генерируются UUID v7, добавлена микросекундная точность и упрощено использование в тестах.
Кеширование HTTP-клиента: Представлено клиентское кеширование HTTP, соответствующее стандарту RFC 9111, на базе компонента Cache.
Валидация видеофайлов: Добавлено новое ограничение для проверки видео с возможностью контроля размеров, кодеков и форматов.
Взвешенные переходы Workflow: Введена поддержка переходов с весами, что позволяет обрабатывать несколько экземпляров и моделировать процессы с количественными требованиями (например, согласования).
Улучшенные исключения в терминале: Теперь в терминале отображаются чистые и читаемые трассировки исключений вместо подробных HTML-дампов.
Общая директория share/: Появилась новая директория для хранения данных, общих для нескольких серверов (например, кешей приложения).
Улучшенная фильтрация валют: Обработка валют стала умнее: автоматически исключаются устаревшие валюты, добавлены новые опции для валидации и отображения только актуальных.
Многошаговые формы: Введена концепция "потоков форм" (form flows) для создания многоэтапных форм с использованием привычных подходов Symfony.
Улучшенные вызываемые команды: Добавлена поддержка enum, ввода на основе DTO, интерактивных подсказок и полная совместимость с тестированием.
Вынос вспомогательных методов контроллера: Представлен новый способ использования помощников контроллера без наследования от базового класса, что упрощает создание и тестирование независимых от фреймворка контроллеров.
Улучшения атрибутов: Расширены возможности атрибутов для маршрутизации, безопасности и событий.
Улучшения класса Request: Внесены ключевые изменения, включая устаревание некоторых методов, расширенный парсинг тела запроса для большего числа HTTP-методов и более строгий контроль переопределения методов.
Улучшения для разработчиков (Часть 1): Множественные улучшения, начиная от умных помощников для форм и консоли, заканчивая лучшей отладкой, локализацией и конфигурацией сервисов.
Улучшения для разработчиков (Часть 2): Упрощена работа с сессиями в тестах, улучшена отладка маршрутов, повышена доступность форм и добавлена нативная интеграция с FrankenPHP.
Подпись сообщений Messenger: В компонент Messenger добавлена возможность подписи сообщений, что гарантирует их целостность до обработки.
Улучшенная PHP-конфигурация: Устаревший "текучий" (fluent) PHP-конфиг заменен на новый массивный формат с полной поддержкой автодополнения, статического анализа и динамической генерацией структур.
Расширение валидации и сериализации через PHP-атрибуты: Добавлены новые PHP-атрибуты для расширения метаданных валидации и сериализации классов, которыми вы не управляете.
Прочие улучшения (Часть 1): Более быстрый нативный HTML5-парсинг, гибкая валидация URL, улучшенная обработка заголовка Link, поддержка HTTP-метода QUERY и упрощенная конфигурация тегов ресурсов.
Прочие улучшения (Часть 2): Добавлена поддержка enum в Workflow, новые возможности контроля XML CDATA, хранилище блокировок DynamoDB, новые Doctrine-типы на основе DatePoint и явные query-параметры при генерации URL.
Прочие улучшения (Часть 3): Структурированная обработка MIME-суффиксов, поддержка Microsoft Graph для почты, обработка непереведенных сообщений, новое утверждение для email и улучшения профилировщика для запросов EventSource.
Устаревание XML-конфигурации
С момента своего появления Symfony поддерживала три формата конфигурации: PHP, YAML и XML. Все они обладали практически идентичными возможностями и производительностью, поскольку компилировались в PHP код перед запуском.
В последних версиях Symfony поддержка XML по умолчанию была отключена для пакетов и маршрутов. Для её повторной активации требовалось вручную обновить методы configureContainer() и/или configureRoutes() в файле src/Kernel.php.
В Symfony 7.4 XML-конфигурация официально объявлена устаревшей. Начиная с версии Symfony 8.0, этот формат больше не будет поддерживаться. YAML останется форматом по умолчанию, используемым Symfony и её рецептами (recipes), однако вы также можете выбрать PHP, если предпочитаете полностью кодоориентированную конфигурацию.
Для повторно используемых бандлов (bundles) XML долгое время оставался популярным форматом, так как много лет был официально рекомендуемым вариантом. Вы можете воспользоваться специальным инструментом для автоматического преобразования XML-конфигурации вашего бандла в PHP.
Параллельно с этим упразднением, Symfony 7.4 улучшает оставшиеся форматы важными новыми функциями.
Улучшенное автодополнение для YAML
JSON-схемы описывают структуру, ограничения и типы данных JSON-документов и совместимых с ним форматов, таких как YAML. В связке с поддерживающим их редактором или валидатором (например, встроенными в современные IDE вроде PHPStorm) они обеспечивают проверку в реальном времени и автодополнение.
В Symfony 7.4 появились новые схемы для конфигурации сервисов и маршрутов, а также для метаданных валидации и сериализации. Поэтому обновленные рецепты Symfony теперь включают специальную директиву $schema: в начале YAML-файлов, которая указывает на соответствующую схему. Это позволяет среде разработки "понимать" структуру конфигурационного файла и помогать вам при его редактировании.
Расширенные массивы (Array Shapes) для PHP
Мы также исследуем новые способы сделать PHP-конфигурацию более выразительной. В Symfony 7.4 мы представляем расширенные структуры массивов (array shapes). Они позволяют конфигурировать приложение, используя структуры, похожие на YAML, но написанные на чистом PHP.
Это позволяет определять маршруты в PHP в виде ассоциативного массива, где ключ — это имя маршрута, а значение — его параметры. Аналогичным образом можно описывать и другую конфигурацию, например, для пакетов: в виде вложенного массива с названием бандла в качестве ключа и его настройками в качестве значения.
Эти структурированные массивы могут использоваться статическими анализаторами и IDE для предоставления более качественной информации и автодополнения, хотя конечный опыт будет зависеть от возможностей вашего редактора кода.
Улучшения механизма Security Voter
Symfony уже предоставляет функции Twig is_granted() и is_granted_for_user(), позволяющие проверять права доступа с помощью voters прямо в шаблонах. Эти функции возвращают логическое значение (true/false), указывающее, имеет ли текущий или указанный пользователь запрашиваемый атрибут безопасности.
В Symfony 7.4 добавляются две новые функции Twig: access_decision() и access_decision_for_user(). Вместо простого булева значения они возвращают объект AccessDecision. Этот объект (DTO) хранит в себе итоговое решение о доступе, коллекцию всех отдельных "голосов" (votes), результирующее сообщение (например, "Доступ разрешен" или пользовательское сообщение об отказе) и другую вспомогательную информацию.
На практике это позволяет в шаблоне не только узнать, разрешен ли доступ, но и получить детализированную причину решения. Например, можно проверить решение, а затем безопасно отобразить для конечного пользователя связанное с ним сообщение, если доступ запрещен.
Добавление метаданных к объектам Vote
В Symfony 7.3 был представлен объект Vote как часть функционала, объясняющего решения voters. В Symfony 7.4 его возможности расширены: теперь к каждому голосу можно прикрепить произвольные метаданные.
Внутри вашего security voter используйте свойство extraData объекта Vote, чтобы добавить любое пользовательское значение. Это значение может быть любого типа, а не только строковым.
Эта новая возможность особенно полезна при определении пользовательской стратегии принятия решений о доступе. По умолчанию голос в Symfony может только разрешить, запретить или воздержаться, и все голоса имеют равный вес. В пользовательской стратегии вы можете, например, присвоить каждому голосу оценку или вес (например, $vote->extraData['score'] = 10;) и использовать это значение при агрегации итоговых результатов.
Таким образом, вы получаете гибкий инструмент для реализации сложной логики принятия решений, где разные voters могут вносить различный вклад в окончательный вердикт на основе переданных метаданных.
Улучшения компонента Uid
Компонент Uid предоставляет утилиты для работы с уникальными идентификаторами, такими как UUID и ULID. В Symfony 7.4 было добавлено несколько новых функций, связанных с UUID.
UUID v7 по умолчанию
UUID v7 — это недавнее дополнение к спецификации UUID, которое генерирует идентификаторы, упорядоченные по времени, на основе высокоточного таймстампа Unix. Это улучшенная версия по сравнению с UUID v1 и v6, и теперь она является рекомендуемым вариантом вместо этих устаревших версий.
Начиная с Symfony 7.4, UUID v7 используется по умолчанию при создании значений через фабрику (UuidFactory). Это означает, что при вызове методов для создания нового UUID или timestamp-based UUID будет генерироваться именно седьмая версия.
Если вам необходима генерация другой версии UUID, вы можете настроить значения по умолчанию в конфигурации фреймворка, указав нужные номера версий для обычных и временных UUID.
Добавление микросекундной точности для UUID v7
Временная составляющая значений UUID v7 обеспечивает точность до миллисекунды. Однако спецификация UUID упоминает, что возможно использование дополнительной точности часов для обеспечения порядка значений с точностью выше миллисекунды.
В Symfony 7.4 мы обновили генерацию UUID v7, включив в неё микросекундную точность. Вам не нужно ничего делать, чтобы воспользоваться этим нововведением. Просто обновитесь до Symfony 7.4, и любые новые создаваемые UUID будут иметь эту повышенную точность. Это также принесло приятный бонус в виде повышения производительности — время генерации сократилось на 10%.
Тестовая фабрика для UUID
Многие версии UUID включают случайные или зависящие от времени части, что затрудняет их использование в тестах. В Symfony 7.4 мы представляем MockUuidFactory, чтобы сделать ваши UUID предсказуемыми и воспроизводимыми в тестовой среде.
Во-первых, сервисы, использующие UUID, должны зависеть от фабрики UuidFactory для их создания. Это означает, что вместо прямого вызова конструктора UUID, сервис получает фабрику через внедрение зависимости и использует её.
Затем, при тестировании таких сервисов, вы можете использовать MockUuidFactory. Вы передаёте ей заранее определённый список UUID, которые будут последовательно возвращаться при каждом вызове метода создания нового идентификатора. Это позволяет вам точно знать, какое значение будет сгенерировано, и делать детерминированные проверки (assertions) в тестах.
Кроме метода create(), мок-фабрика также поддерживает методы randomBased(), timeBased() и nameBased(). Вы также можете смешивать разные версии UUID в списке возвращаемых значений для более сложных сценариев тестирования.
Кеширование HTTP-клиента
Компонент HttpClient предоставляет функцию кеширования для предотвращения повторных HTTP-запросов к одному и тому же контенту. Ранее внутри использовался класс HttpCache из компонента HttpKernel.
В Symfony 7.4 мы переработали эту функцию, чтобы отказаться от HttpCache, основать кеширование на компоненте Cache и сделать реализацию полностью соответствующей стандарту RFC 9111.
Настройка кеширования
Процесс настройки стал проще и интегрированным. Вот как это работает:
1. Определите пул кеша (cache pool) с адаптером, поддерживающим теги (tag-aware). Это делается в конфигурации фреймворка. Например, можно использовать Redis.
2. Добавьте новую опцию caching в конфигурацию своего HTTP-клиента. В этой опции укажите, какой пул кеша следует использовать.
После этой настройки все запросы, отправленные с помощью данного клиента, будут автоматически кешироваться в соответствии со стандартом RFC 9111. Это означает, что клиент будет интеллектуально учитывать заголовки кеширования от сервера (как, например, Cache-Control), обеспечивая корректное поведение.
Дополнительные параметры
Опция caching принимает два дополнительных ключа для тонкой настройки:
shared: Если установлено значение true (по умолчанию), клиент использует общий кеш. Это позволяет повторно использовать закешированные ответы между разными пользователями, что повышает эффективность.
max_ttl: По умолчанию ответы хранятся в кеше столько времени, сколько указано сервером в заголовке TTL (Time to Live). Эта опция позволяет установить верхний предел для этого времени, ограничивая срок жизни записей в кеше заданным значением.
Таким образом, нововведение предлагает более современный, стандартизированный и удобный способ организации HTTP-кеширования на стороне клиента, встроенный прямо в конфигурацию Symfony.
Ограничение Video для валидации
Компонент Symfony Validator предоставляет десятки встроенных ограничений (constraints) для проверки данных любого типа. В Symfony 7.4 добавлено новое ограничение Video, предназначенное для валидации видеофайлов.
Ограничение Video работает аналогично существующему ограничению Image, но специально разработано для видеофайлов и включает соответствующие опции проверки. Перед его использованием необходимо установить FFmpeg, который предоставляет инструмент ffprobe, используемый для извлечения и анализа метаданных видео.
Это ограничение позволяет накладывать требования к следующим параметрам:
Размеры и пропорции: ширина, высота, количество пикселей, соотношение сторон.
Технические характеристики: видеокодек, контейнер (формат файла).
Ориентация: можно разрешить или запретить альбомные (landscape), портретные (portrait) или квадратные (square) видео.
Прочие параметры: максимальный размер файла, допустимые MIME-типы.
Например, с его помощью можно гарантировать, что загружаемое видео соответствует стандарту Full HD (1080p), не превышает размер в 100 мегабайт и имеет формат MP4 или WebM.
По умолчанию ограничение принимает распространенные видеокодеки (H.264, HEVC, VP9, AV1) и форматы контейнеров (MP4, WebM, MKV). Однако вы можете гибко настроить эти списки, указав только те кодеки и контейнеры, которые соответствуют вашим конкретным требованиям.
Таким образом, новое ограничение предоставляет мощный и детализированный инструмент для контроля качества и соответствия видеофайлов, загружаемых в ваше приложение.
Взвешенные переходы в Workflow
Компонент Workflow в Symfony моделирует бизнес-процессы как последовательность мест (местоположений или шагов), соединенных переходами (действиями, перемещающими объект между местами). Прогресс объекта отслеживается через "отметку" (marking), которая фиксирует, в каких местах он находится.
Ключевое отличие Workflow от State Machine в том, что объект может находиться в нескольких местах одновременно. Это полезно для моделирования параллельных процессов. Однако до сих пор каждое место могло лишь фиксировать факт присутствия объекта, как бинарный флаг.
Symfony 7.4 вводит концепцию кратности (multiplicity) с помощью взвешенных переходов. Теперь место может отслеживать, сколько раз объект в нем находится. Это незаменимо, когда для продолжения процесса требуется несколько экземпляров чего-либо: например, «собрать 4 ножки перед сборкой стола» или «дождаться 3 согласований перед публикацией».
Как работают взвешенные переходы
Переходу можно назначить "вес", определяющий количество требуемых или производимых экземпляров:
- Вес на выходе (to): переход помещает объект в целевое место N раз.
- Вес на входе (from): переход требует, чтобы объект находился в исходном месте N раз, прежде чем его можно будет выполнить.
Без указания веса каждый переход по умолчанию потребляет или создает ровно один экземпляр на место.
Пример: Сборка стола
Рассмотрим workflow для сборки стола. Нужно 4 ножки, 1 столешница, а также нужно отслеживать время.
Логика процесса:
- Начальный переход
startпомещает объект в состояниеprepare_leg4 раза (для ножек), вprepare_top1 раз (для столешницы) и вstopwatch_running1 раз (для таймера). - Каждый переход
build_legзабирает один экземпляр изprepare_legи добавляет один вleg_created. Его нужно выполнить ровно 4 раза. - Переход
build_topсоздает одну столешницу. - Финальный переход
joinтребует, чтобы объект находился вleg_createdровно 4 раза, и по одному разу в остальных необходимых местах (top_created,stopwatch_running). Только тогда сборка будет завершена.
Что это дает: Система создает точку синхронизации. Вы не сможете перейти к сборке, пока все необходимые компоненты не достигнут заданного количества. Workflow автоматически обеспечивает эти структурные ограничения на уровне модели, делая процесс надежным и предсказуемым.
Улучшенный вывод исключений в терминале
При запуске Symfony-приложений в режиме отладки исключения отображаются в браузере на удобной странице с подробной трассировкой стека и инструментами для мгновенной диагностики проблем.
Однако при возникновении исключения в консоли (например, во время запуска тестов) эта же HTML-страница всегда выводилась прямо в терминал. Вместо чистого, читаемого сообщения об ошибке разработчики видели сотни строк сырого HTML, CSS и JavaScript, что захламляло вывод и сильно затрудняло анализ.
Долгое время это было одной из самых неприятных особенностей процесса тестирования в Symfony. Предыдущие версии пытались смягчить проблему, добавляя основное сообщение об исключении в виде HTML-комментариев в начало и конец вывода, но это не решало её кардинально.
В Symfony 7.4 эта проблема наконец исправлена. Теперь исключения в терминале отображаются в виде чистых, читаемых текстовых трассировок стека — именно так, как этого и следовало ожидать.
Symfony 7.4 автоматически выбирает подходящий механизм рендеринга ошибок в зависимости от среды выполнения. Технически, для принятия решения о том, когда рендерить ошибку как HTML, а когда как обычный текст, используется параметр kernel.runtime_mode.
Это значение устанавливается автоматически на основе контекста выполнения (браузер или консоль), но вы также можете контролировать его явно, задав переменную окружения APP_RUNTIME_MODE. Это нововведение значительно улучшает опыт разработки и отладки при работе через командную строку.
Общая директория Share Directory
Symfony хранит кеши двух типов в директории var/cache/: системный и прикладной. Однако в архитектурах с несколькими серверами у этих типов кеша возникают противоречивые требования:
- Системный кеш (скомпилированный контейнер, маршруты, оптимизированные классы и т.д.) должен быть локальным для каждого сервера для максимальной производительности. Его не нужно синхронизировать между серверами, так как он идентичен на всех экземплярах.
- Прикладной кеш (например, пулы
cache.app) должен быть общим для всех серверов в кластере, чтобы поддерживать консистентность данных.
Текущее распространенное решение — монтировать всю директорию var/cache/ на общее сетевое хранилище (NFS, EFS и т.п.). Это работает, но снижает производительность, поскольку заставляет быстрый системный кеш использовать медленное сетевое хранилище вместо быстрых локальных дисков.
В Symfony 7.4 мы представляем новую концепцию, решающую эту проблему: директорию share/. Это специальная директория для данных, которые должны быть общими между серверами.
Доступ к этой новой директории можно получить через:
- Новый метод
KernelInterface::getShareDir(). - Новую переменную окружения
APP_SHARE_DIR. - Новый параметр контейнера
%kernel.share_dir%.
Для обеспечения обратной совместимости метод getShareDir() по умолчанию возвращает то же значение, что и getCacheDir(). Однако в новых приложениях Symfony 7.4 в файле .env будет определена отдельная переменная, например: APP_SHARE_DIR=$APP_PROJECT_DIR/var/share.
Что изменится: Все пулы кеша, производные от адаптера app (cache.app), теперь по умолчанию будут хранить свои данные в %kernel.share_dir%/pools/app, а не в %kernel.cache_dir%/pools/app.
Назначение директории: Директория share/ не ограничивается только пулами кеша. Она предназначена для любых данных, общих для всех фронтенд-серверов в кластере. Например:
var/share/pools/— прикладные пулы кеширования.var/share/http_cache/— хранилище HTTP-кеша.var/share/storage/— локальное хранилище Flysystem.var/share/db/— SQLite базы данных.
Это разделение позволяет оптимизировать производительность, храня системный кеш локально, а общие данные — в доступном всем серверам месте.
Улучшенная фильтрация валют
По умолчанию класс Currencies из компонента Intl и поле формы CurrencyType отображают все валюты, определённые стандартом ISO 4217.
Этот список включает устаревшие валюты, такие как немецкая марка или ирландский фунт, которые были заменены евро десятилетия назад. Для электронной коммерции или платежных приложений показ вышедших из обращения валют не имеет смысла и создает плохой пользовательский опыт.
Symfony 7.4 решает эту проблему, скрывая устаревшие валюты по умолчанию и вводя новые методы для проверки и фильтрации валют на основе их статуса законного платежного средства и временных периодов действия.
Новые помощники в Intl
Класс Currencies теперь включает методы для фильтрации валют по стране и дате, используя метаданные ICU для определения их статуса и периода обращения:
Currencies::forCountry()— позволяет получить все активные и законные валюты для заданной страны на сегодняшний день или на конкретную историческую дату.Currencies::isValidInCountry()— проверяет, действительна ли конкретная валюта для указанной страны.
Например, можно легко получить список всех валют, которые были в обращении в Испании 1 января 1982 года, или проверить, является ли швейцарский франк (CHF) действительной валютой для Швейцарии.
Новые опции для типа формы CurrencyType
Поле формы выбора валюты теперь включает три новые опции для фильтрации отображаемого списка:
legal_tender(по умолчаниюtrueв 7.4): Определяет, показывать ли только законные платежные средства (true), только незаконные (false) или все валюты (null).active_at: Показывает только валюты, находившиеся в обращении на конкретную дату.not_active_at: Показывает только валюты, вышедшие из обращения на конкретную дату.
Эти опции позволяют легко создавать селекторы валют, которые показывают пользователям только релевантные и актуальные варианты, адаптированные под конкретную страну или исторический период, значительно улучшая UX форм.
Многошаговые формы (Form Flows)
Формы Symfony — это проверенная временем функция для создания даже самых сложных форм. Они предоставляют десятки встроенных типов полей, расширенную валидацию, события для динамического поведения, поддержку вложенных коллекций полей и многое другое.
В Symfony 7.4 мы улучшаем формы, представляя концепцию многошаговых форм (Form Flows). Это позволяет разбивать большие формы на меньшие, связанные между собой этапы, по которым пользователь может перемещаться, пока процесс не будет завершен.
Основные принципы Form Flows
Эти новые многошаговые формы называются "потоками форм" (form flows) и следуют тем же основным концепциям, что и обычные формы. Рассмотрим приложение, которое определяет класс UserSignUp для данных нового пользователя. Трехэтапная форма регистрации создается следующим образом:
- Вместо расширения базового класса
AbstractTypeтеперь используетсяAbstractFlowType. - Вместо метода
buildForm()используетсяbuildFormFlow(). - Каждый шаг формы определяется как независимая, обычная форма Symfony. Затем он добавляется в поток с помощью метода
addStep()с указанием уникального имени. - В конфигурации можно указать свойство объекта данных (например,
currentStep), в котором будет автоматически храниться имя текущего активного шага.
Обработка в контроллере
Создание и обработка такой многошаговой формы в контроллере практически не отличается от работы с обычной формой. Ключевых отличий всего два:
- Необходима дополнительная проверка
$flow->isFinished(), чтобы узнать, когда форма завершена (например, пользователь нажал финальную кнопку отправки). - При рендеринге необходимо вызвать
$flow->getStepForm(), чтобы получить объект формы для текущего шага.
Валидация по шагам
Form Flows вводят полезное соглашение для валидации: они автоматически устанавливают имя текущего шага в качестве активной группы валидации. Это позволяет применять ограничения валидации только к данным текущего этапа, используя атрибут Valid с параметром groups.
Навигация между шагами
Навигацией управляют специальные типы кнопок, которые расширяют ButtonFlowType:
ResetFlowType— сбрасывает форму в начальное состояние.PreviousFlowType— возвращает на предыдущий шаг.NextFlowType— переходит к следующему шагу.FinishFlowType— завершает процесс и помечает форму как завершенную.
Эти кнопки поддерживают опции вроде skip, back_to, include_if и clear_submission, что позволяет реализовывать условные шаги, сложную навигацию и нелинейные сценарии.
Таким образом, Form Flows предоставляют мощный, но знакомый инструмент для создания сложных многоэтапных процессов, таких как регистрация, оформление заказа или многошаговые опросы, с сохранением всех преимуществ экосистемы форм Symfony.
Опубликовано:

