Несколько месяцев назад я написал статью о замечательном Symfony ParamConverter.
Цель этого ParamConverter проста: на основе маршрута контроллера он автоматически находит искомый элемент, делая запрос к базе данных и возвращая его. ошибка 404, если элемент не найден. Это экономит много времени и уменьшает размер кода, что упрощает его чтение и обслуживание.

Благодаря Robin Chalas, который прокомментировал мою предыдущую статью и блог Symfony, я обнаружил совершенно новый Symfony EntityValueResolver, который поставляется с атрибутом PHP, выпущенным с Symfony 6.2 в качестве замены ParamConverter: MapEntity.

Как это работает?

Что ж, если вы уже знакомы с ParamConverter, на самом деле в коде нет никаких изменений 😝
Действительно, большую часть времени на самом деле нет никакого специального кода, который можно было бы добавить для использования EntityValueResolver!

Здесь распознаватель пытается получить объект Product из атрибута запроса, доступного в атрибуте Route (здесь id), точно так же, как это сделал paramConverter.

В любом случае есть одно большое изменение для тех, кто использует paramConverter: EntityValueResolver и его атрибут MapEntity напрямую реализованы в Symfony, тогда как paramConverter происходит из внешнего (и устаревшего) пакета SensioFrameworkExtraBundle. Таким образом, использование MapEntity вместо paramConverter означает, что вам больше не нужен устаревший SensioFrameworkExtraBundle (если только вам не нужны другие его функции 😊)!

Как это работает?

Как объяснено в приведенном выше примере, преобразователь пытается получить объект из параметра запроса, доступного в атрибуте Route(идентификатор в примере). Это означает, что имя параметра маршрута должно совпадать с сущностью. Вы будете использовать этот «автоматический» преобразователь почти в 80% случаев, но для некоторых конкретных случаев использования у вас будет несколько дополнительных действий.

Как использовать его с несколькими объектами?

Если параметр запроса не совпадает с параметром объекта или если маршрут более сложный (например, ссылка на несколько объектов), нам нужно использовать атрибут MapEntity.

Как видно из следующего примера, нам нужно импортировать MapEntity, чтобы использовать его, а затем мы вызываем атрибут непосредственно в сигнатуре функции.

Здесь MapEntity вызовет функцию find($id), поскольку мы использовали параметр «id» MapEntity. В основном мы говорим, что идентификатор объекта (в общем случае переменная $id) соответствует выбранному параметру маршрута.

В следующем примере показано, как тот же результат был получен с прежним paramConverter. Все было выше самой функции, и я должен признать, что на первый взгляд это казалось более естественным, но в конце концов атрибут MapEntity оказался гораздо полезнее.

MapEntity с параметром без идентификатора

В других случаях вам нужно будет найти сущность по свойству, которое не является идентификатором сущности. Сделать это с помощью MapEntity очень просто благодаря параметру mapping, который получает массив ключ/значение (параметр маршрута =› параметр объекта).
Например, в следующем коде мы получаем продукт по его слагу.

Для этого использования вместо вызова метода find($id) MapEntity вызовет метод findOneBy().

Идти дальше

Мы увидели самую важную часть EntityValueResolver и MapEntity, которая уже должна покрывать большую часть ваших потребностей в любом проекте. Но другие возможности упущены, и я настоятельно рекомендую вам проверить документацию Symfony, чтобы узнать больше об этой замечательной функции!

https://symfony.com/doc/current/doctrine.html#mapentity-options