Open
Description
Description
Mapping attributes for controller arguments are a mix of different concepts.
#[MapEntity], #[MapDateTime] - are "map to what".
#[MapQueryString], #[MapQueryParameter], #[MapRequestPayload], #[MapUploadedFile] - are "map from where".
Moreover, they can not be combined, as such you can not do
#[MapEntity]
#[MapQueryParameter]
Post $post
Providing a value resolver in most cases would not work either:
#[MapQueryParameter(resolver: EntityValueResolver::class)]
Post $post
The problem is ValueResolvers are hardcoded to check only a single input bag (Entity- and DateTimeValueResolver check only request attributes).
Proposed solution:
- Introduce the \Symfony\Component\HttpKernel\Attribute\ValueConsumer base attribute
- Introduce a set of ValueConsumer attributes:
- #[RouteParam], #[QueryParam], #[QueryString], #[BodyParam], #[BodyPayload], #[HeaderParam]
- can be combined in order to support cases when the value can be sent either in query or post data.
- Add optional third param in ValueResolverInterface::resolve:
interface ValueResolverInterface
{
public function resolve(Request $request, ArgumentMetadata $argument, mixed $value = null): iterable;
}
- in \Symfony\Component\HttpKernel\Controller\ArgumentResolver::getArguments() before calling resolvers, run through ValueConsumer attributes defined for argument until one returning a value, then pass this value to resolve().
- Update all ValueResolvers to use $value if provided. If not, fallback to their original logic.
Example
#[Route('/posts/cat/{category}/{date?}')]
public function posts(
#[RouteParam]
PostCategory $category,
#[RouteParam('date')]
#[QueryParam]
?\DateTimeInterface $dateFrom,
#[RouteParam('date')]
#[QueryParam]
?\DateTimeInterface $dateTo,
) {
// /posts/cat/1/2024-10-25, same as:
// /posts/cat/1?dateFrom=2024-10-25&dateTo=2024-10-25
}
Metadata
Metadata
Assignees
Labels
RFC = Request For Comments (proposals about features that you want to be discussed)RFC = Request For Comments (proposals about features that you want to be discussed)