Extending Action Argument Resolving ¶
In the controller guide, you've learned that you can get the
Request object via an argument in
your controller. This argument has to be type-hinted by the Request
class
in order to be recognized. This is done via the
ArgumentResolver. By
creating and registering custom value resolvers, you can extend this
functionality.
Built-In Value Resolvers ¶
Symfony ships with the following value resolvers in the HttpKernel component:
- BackedEnumValueResolver
-
Attempts to resolve a backed enum case from a route path parameter that matches the name of the argument. Leads to a 404 Not Found response if the value isn't a valid backing value for the enum type.
引数の名前に一致するルート パス パラメーターから、裏付けられた列挙型のケースを解決しようとします。値が列挙型の有効な裏付け値でない場合は、404 Not Found 応答につながります。For example, if your backed enum is:
たとえば、バックアップされた列挙型が次の場合:1 2 3 4 5 6 7 8 9
namespace App\Model; enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; }
And your controller contains the following:
また、コントローラーには次のものが含まれています。1 2 3 4 5 6 7 8 9 10
class CardController { #[Route('/cards/{suit}')] public function list(Suit $suit): Response { // ... } // ... }
When requesting the
/cards/H
URL, the$suit
variable will store theSuit::Hearts
case./cards/H URL を要求すると、$suit 変数は theSuit::Hearts ケースを格納します。Furthermore, you can limit route parameter's allowed values to only one (or more) with
EnumRequirement
:さらに、EnumRequirement を使用して、ルート パラメーターの許容値を 1 つ (または複数) のみに制限できます。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
use Symfony\Component\Routing\Requirement\EnumRequirement; // ... class CardController { #[Route('/cards/{suit}', requirements: [ // this allows all values defined in the Enum 'suit' => new EnumRequirement(Suit::class), // this restricts the possible values to the Enum values listed here 'suit' => new EnumRequirement([Suit::Diamonds, Suit::Spades]), ])] public function list(Suit $suit): Response { // ... } // ... }
The example above allows requesting only
/cards/D
and/cards/S
URLs and leads to 404 Not Found response in two other cases.上記の例では、/cards/D と /cards/SURLs のみを要求でき、他の 2 つのケースでは 404 Not Found 応答が返されます。6.1
6.1The
BackedEnumValueResolver
andEnumRequirement
were introduced in Symfony 6.1.BackedEnumValueResolver と EnumRequirement は Symfony 6.1 で導入されました。 - RequestAttributeValueResolver
-
Attempts to find a request attribute that matches the name of the argument.
引数の名前に一致するリクエスト属性を見つけようとします。
- DateTimeValueResolver
-
Attempts to find a request attribute that matches the name of the argument and injects a
DateTimeInterface
object if type-hinted with a class extendingDateTimeInterface
.引数の名前に一致するリクエスト属性を見つけようとし、DateTimeInterface を拡張するクラスでタイプヒントされている場合は DateTimeInterface オブジェクトを挿入します。By default any input that can be parsed as a date string by PHP is accepted. You can restrict how the input can be formatted with the MapDateTime attribute.
デフォルトでは、PHP によって日付文字列として解析できるすべての入力が受け入れられます。MapDateTime 属性を使用して、入力のフォーマット方法を制限できます。6.1
6.1The
DateTimeValueResolver
was introduced in Symfony 6.1.DateTimeValueResolver は Symfony 6.1 で導入されました。 - RequestValueResolver
-
Injects the current
Request
if type-hinted withRequest
or a class extendingRequest
.Request または classextending Request で型ヒンティングされている場合、現在の Request を注入します。 - ServiceValueResolver
-
Injects a service if type-hinted with a valid service class or interface. This
works like autowiring.
有効なサービス クラスまたはインターフェイスでタイプ ヒンティングされている場合は、サービスを注入します。これは自動配線のように機能します。
- SessionValueResolver
-
Injects the configured session class implementing
SessionInterface
if type-hinted withSessionInterface
or a class implementingSessionInterface
.SessionInterface または SessionInterface を実装するクラスで型ヒントされた場合に、SessionInterface を実装する構成済みのセッション クラスを注入します。 - DefaultValueResolver
-
Will set the default value of the argument if present and the argument
is optional.
引数が存在し、引数がオプションの場合、引数のデフォルト値を設定します。
- UidValueResolver
-
Attempts to convert any UID values from a route path parameter into UID objects. Leads to a 404 Not Found response if the value isn't a valid UID.
ルート パス パラメーターの UID 値を UID オブジェクトに変換しようとします。値が有効な UID でない場合は、404 Not Found 応答が返されます。For example, the following will convert the token parameter into a
UuidV4
object:たとえば、次の例ではトークン パラメータが UuidV4 オブジェクトに変換されます。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// src/Controller/DefaultController.php namespace App\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Uid\UuidV4; class DefaultController { #[Route('/share/{token}')] public function share(UuidV4 $token): Response { // ... } }
6.1
6.1The
UidValueResolver
was introduced in Symfony 6.1.UidValueResolver は Symfony 6.1 で導入されました。 - VariadicValueResolver
-
Verifies if the request data is an array and will add all of them to the
argument list. When the action is called, the last (variadic) argument will
contain all the values of this array.
リクエスト データが配列であるかどうかを確認し、それらすべてを引数リストに追加します。アクションが呼び出されると、最後の (可変個の) 引数には、この配列のすべての値が含まれます。
In addition, some components, bridges and official bundles provide other value resolvers:
- UserValueResolver
-
Injects the object that represents the current logged in user if type-hinted with
UserInterface
. You can also type-hint your ownUser
class but you must then add the#[CurrentUser]
attribute to the argument. Default value can be set tonull
in case the controller can be accessed by anonymous users. It requires installing the SecurityBundle.UserInterface で型ヒンティングされている場合、現在ログインしているユーザーを表すオブジェクトを挿入します。独自の User クラスをタイプヒントすることもできますが、その場合は #[CurrentUser] 属性を引数に追加する必要があります。匿名ユーザーがコントローラーにアクセスできる場合は、デフォルト値を null に設定できます。 SecurityBundle をインストールする必要があります。If the argument is not nullable and there is no logged in user or the logged in user has a user class not matching the type-hinted class, an
AccessDeniedException
is thrown by the resolver to prevent access to the controller.引数が null 可能ではなく、ログインしているユーザーがいない場合、またはログインしているユーザーのユーザー クラスが型ヒント クラスと一致しない場合、リゾルバーによって AccessDeniedException がスローされ、コントローラーへのアクセスが防止されます。 - EntityValueResolver
-
Automatically query for an entity and pass it as an argument to your controller.
エンティティを自動的にクエリし、それを引数としてコントローラーに渡します。For example, the following will query the
Product
entity which has{id}
as primary key:たとえば、次のクエリは、主キーとして {id} を持つ Product エンティティを照会します。1 2 3 4 5 6 7 8 9 10 11 12 13 14
// src/Controller/DefaultController.php namespace App\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class DefaultController { #[Route('/product/{id}')] public function share(Product $product): Response { // ... } }
To learn more about the use of the
EntityValueResolver
, see the dedicated section Automatically Fetching Objects.EntityValueResolver の使用の詳細については、専用のセクション「オブジェクトの自動取得」を参照してください。6.2
6.2The
EntityValueResolver
was introduced in Symfony 6.2.EntityValueResolver は Symfony 6.2 で導入されました。 - PSR-7 Objects Resolver:
-
Injects a Symfony HttpFoundation
Request
object created from a PSR-7 object of type ServerRequestInterface, RequestInterface or MessageInterface. It requires installing the PSR-7 Bridge component.タイプ ServerRequestInterface、RequestInterface、または MessageInterface の PSR-7 オブジェクトから作成された Symfony HttpFoundation Request オブジェクトを挿入します。PSR-7 Bridge コンポーネントをインストールする必要があります。
Adding a Custom Value Resolver ¶
In the next example, you'll create a value resolver to inject an ID value
object whenever a controller argument has a type implementing
IdentifierInterface
(e.g. BookingId
):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// src/Controller/BookingController.php
namespace App\Controller;
use App\Reservation\BookingId;
use Symfony\Component\HttpFoundation\Response;
class BookingController
{
public function index(BookingId $id): Response
{
// ... do something with $id
}
}
|
6.2
The ValueResolverInterface
was introduced in Symfony 6.2. Prior to
6.2, you had to use the
ArgumentValueResolverInterface,
which defines different methods.
Adding a new value resolver requires creating a class that implements ValueResolverInterface and defining a service for it.
This interface contains a resolve()
method, which is called for each
argument of the controller. It receives the current Request
object and an
ArgumentMetadata
instance, which contains all information from the method signature.
The resolve()
method should return either an empty array (if it cannot resolve
this argument) or an array with the resolved value(s). Usually arguments are
resolved as a single value, but variadic arguments require resolving multiple
values. That's why you must always return an array, even for single values:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// src/ValueResolver/IdentifierValueResolver.php
namespace App\ValueResolver;
use App\IdentifierInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
class BookingIdValueResolver implements ValueResolverInterface
{
public function resolve(Request $request, ArgumentMetadata $argument): array
{
// get the argument type (e.g. BookingId)
$argumentType = $argument->getType();
if (
!$argumentType
|| !is_subclass_of($argumentType, IdentifierInterface::class, true)
) {
return [];
}
// get the value from the request, based on the argument name
$value = $request->attributes->get($argument->getName());
if (!is_string($value)) {
return [];
}
// create and return the value object
return [$argumentType::fromString($value)];
}
}
|
This method first checks whether it can resolve the value:
- The argument must be type-hinted with a class implementing a custom
IdentifierInterface
;引数は、カスタム IdentifierInterface を実装するクラスで型ヒントを指定する必要があります。 - The argument name (e.g.
$id
) must match the name of a request attribute (e.g. using a/booking/{id}
route placeholder).引数名 (例: $id) は requestattribute の名前と一致する必要があります (例: /booking/{id} ルート プレースホルダーを使用)。
When those requirements are met, the method creates a new instance of the custom value object and returns it as the value for this argument.
That's it! Now all you have to do is add the configuration for the service
container. This can be done by tagging the service with controller.argument_value_resolver
and adding a priority:
-
YAML
YAML
-
XML
XML
-
PHP
PHP
1 2 3 4 5 6 7 8 9 10 |
# config/services.yaml
services:
_defaults:
# ... be sure autowiring is enabled
autowire: true
# ...
App\ValueResolver\BookingIdValueResolver:
tags:
- { name: controller.argument_value_resolver, priority: 150 }
|
While adding a priority is optional, it's recommended to add one to make sure
the expected value is injected. The built-in RequestAttributeValueResolver
,
which fetches attributes from the Request
, has a priority of 100
. If your
resolver also fetches Request
attributes, set a priority of 100
or more.
Otherwise, set a priority lower than 100
to make sure the argument resolver
is not triggered when the Request
attribute is present.
To ensure your resolvers are added in the right position you can run the following command to see which argument resolvers are present and in which order they run:
1 |
$ php bin/console debug:container debug.argument_resolver.inner --show-arguments
|