Новое в 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
{
// ...
}
}