-
-
Notifications
You must be signed in to change notification settings - Fork 900
[RFC] Mapping query, path and header parameters to a DTO #7112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
That's a very interesting proposal! I'm not sure the concept of a provider for the Author object works as is though, or at least it probably makes things work very differently from what happens now. What i expect to happen at the sql level is something like : select b.*
from books b
join author a on a.id = b.author_id
where a.name = :name If you use a separate provider to fetch the store first, you'll end up making multiple queries instead. The provider could be a LinksHandler of some sort, but then sharing this "parameter class" between apiresources gets difficult. #[ApiResource(
operations: [
new GetCollection(
uriTemplate: '/store/{id}/books',
parameters: GetBookForStoreParameters::class,
provider: GetBookForStoreProvider::class,
),
],
)]
class Book
{
//...
#[Parameter(from: 'author', link: self::addJoinForAuthor(...)]
public Author $author; The remaining difficulty is that security is also likely to be difficult to reuse, and i don't see an easy solution for this one. |
In my example i consider that author and book may not comes from the same database, like you are fetching book from elasticsearch that only have the author id, and so it must be fetched before hand But in your use case, i imagine that it should be up to the user to do that, if both data are in the same database, and that parameters are link (but more filters) then he could just expect a string for author, and use this string in its custom book provider without having to think about link ? I really don't use that much link so maybe my vision is biased, but IMO you just always need to write a provider that do your own logic when you want something more complex than just a fetch with an id. I find this straightforward and avoid having business logic determined by configuration and more by plain code which is easier to test and understand IMO. |
AFAIK the most common use case currently is that links or filters are basically ways to customize the query used to fetch your resources, so introducing "intermediary" objects is a big shift.
You'd be reimplementing filters by hand in custom providers? That would be a major step back!
I have a different experience indeed. I do use custom providers a LOT, but on the "getting data" side most of them only need to call the default provider (sometimes with reworked uriVariables/context). The largest amount of work they do is mapping the result to the actual ApiResource I want. |
You don't need
You can declare security on parameters and on uri variables. Using a DTO for these is nice but I'm not sure it's that easy to implement. URI Variables and parameters are quite distinct in their usage and representations across standards (graphql, json-ld etc.). A viable solution would be to have a DTO for parameters and one for uri variables. Though, as of today you already have both as This is also quite hard to do: #[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 As you may want more then one uri variable to fetch data, it's what we tried to achieve with the sub-resource automatic system and in the end it's quite hard to use. It's always easier to create a I'll sleep on it though I like the approach (today it'd mean adding a |
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 :
Then we could use this class to declare parameters of an endpoint :
Then in our provider instead of having to use the
$uriVariables
orrequest
field in context we could directly use this objectThis allow to :
Not sure how BC could be supported, but i'm sure we can find something
The text was updated successfully, but these errors were encountered: