Open
Description
This RFC propose to allow using a class to declare parameters, and map those parameters to an object of this class.
As an example we could have a parameters class like this :
use App\Entity\Store;
use ApiPlatform\Metadata\QueryParameter;
use ApiPlatform\Metadata\PathParameter;
use ApiPlatform\Metadata\HeaderParameter;
use Symfony\Component\Validator\Constraints as Assert;
class GetBookForStoreParameters
{
#[QueryParameter]
#[Assert\Range(min: 1, max: 100)] // it is possible to declare constraint
public int $page; // this parameter has no default value, which means it is required, if it is not present then it will return a 400 response
#[QueryParameter(name: 'max')]
public int $maxItemsPerPage = 100; // there is a default value, so it's not required
#[PathParameter(name: 'id', security('is_granted("ROLE_GET_BOOK")')]
public Store $store; // here the store is a doctrine entity and it would use a provider to fetch this, we could also link security check on a parameter
#[QueryParameter(provider: AuthorFromNameProvider::class)]
public ?Author $author = null; // Here we use a custom provider to fetch the author from name
#[HeaderParameter(name: 'X-Custom-Header')]
#[Assert\Length(max: 100)]
public string $customHeader = '';
}
Then we could use this class to declare parameters of an endpoint :
#[ApiResource(
operations: [
new GetCollection(
uriTemplate: '/store/{id}/books',
parameters: GetBookForStoreParameters::class,
provider: GetBookForStoreProvider::class,
),
],
)]
class Book
{
// ...
}
Then in our provider instead of having to use the $uriVariables
or request
field in context we could directly use this object
class GetBookForStoreProvider implements ProviderInterface
{
public function provide(Operation $operation, GetBookForStoreParameters: $parameters): array
{
// At this point i'm sure that our parameters are valid and that security on them has been checked so i can safely use the store
$books = $this->service->getBooksForStoreAndMaybeAuthor($parameters->store, $parameters->author);
return $books;
}
}
This allow to :
- unify uriVariables / parameters / headers declaration into the same object
- add a way to link an object to a parameter (without the fromClass / toProperty which are vague IMO see [RFC] Add a system for getting parent resource and play security #7107)
- provide security easily on those parameters
- provide better static analysis (like a parameter has been removed but was still used in a critical place)
- better reusability of same parameters across operations (by using traits and / or inheritance)
Not sure how BC could be supported, but i'm sure we can find something
Metadata
Metadata
Assignees
Labels
No labels