Новое в Symfony 6.3 — Преобразование целевых значений
В Symfony преобразователи значений аргументов позволяют вводить определённые значения в аргументы контроллеров. Например, если вы указываете какой-либо аргумент контроллера с классом Request из HttpFoundation, Symfony внедряет объект, представляющий текущий запрос.
Symfony предоставляет множество встроенных преобразователей для внедрения сервисов, сеанса, значений UID, значений PHP по умолчанию и т.д. В Symfony 6.3 мы улучшаем эту функцию, чтобы сделать её более мощной. Во-первых, мы вводим новый атрибут ValueResolver для явного выбора используемого преобразователя.
Рассмотрим следующий пример:
// src/Controller/SessionController.php
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
class SessionController
{
#[Route('/')]
public function __invoke(SessionInterface $session = null): Response
{
// ...
}
}Symfony будет вызывать все встроенные преобразователи аргументов по приоритету, пока один из них не предоставит значение для этого аргумента. В этом примере SessionValueResolver (приоритет 50) будет вызывать перед DefaultValueResolver (приоритет -100). Вот почему аргумент $session будет содержать либо текущий объект Session, либо значение null.
Если вы уверены, что в вашем приложении всегда будет сессия, то можно сделать так:
// ...
use Symfony\Component\HttpKernel\Attribute\ValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
class SessionController
{
#[Route('/')]
public function __invoke(
#[ValueResolver(SessionValueResolver::class)]
SessionInterface $session
): Response
{
// ...
}
}Новый атрибут ValueResolver позволяет явно указать Symfony, какой преобразователь следует использовать для получения значения этого аргумента. Для удобства имена всех строенных распознавателей — это их FQCN (например, SessionValueResolver::class).
В дополнение к этому мы добавили ещё один новый атрибут AsTargetedValueResolver для создания явного преобразователей, которые можно вызвать только явно. Рассмотрим следующий преобразователь аргументов, который преобразует значения id бронирования в объекты Booking:
// src/ValueResolver/IdentifierValueResolver.php
namespace App\ValueResolver;
use Symfony\Component\HttpKernel\Attribute\AsTargetedValueResolver;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
#[AsTargetedValueResolver('booking_id')]
class BookingIdValueResolver implements ValueResolverInterface
{
// ...
}Вместо того чтобы разрешить Symfony вызывать этот преобразователь для всех аргументов контроллеров, новый атрибут #[AsTargetedValueResolver] говорит Symfony использовать этот преобразователь только в том случае, если он вызывается явно. Поэтому он будет использоваться только в таких случаях:
// ...
use Symfony\Component\HttpKernel\Attribute\ValueResolver;
class BookingController
{
#[Route('/booking/{id}')]
public function show(#[ValueResolver('booking_id')] Booking $booking): Response
{
// ...
}
}