-
-
Notifications
You must be signed in to change notification settings - Fork 920
Allow GraphQL to filter on nested property #1868
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remember that it can produce a conflict when someone creates a filter with such name.
Please also add a test for order and date filter to make sure it's ok. |
I will add it for date, ordering on nested property doesn't make much sense but I might be missing the point ? |
Consider fetching posts ordered by author's rating (stars). |
I don't really like this way. The issue will be too obscure for an user if it used a custom filter with an underscore. I would prefer the other method. |
Sure I figured out just after commenting. this patch will need more work because the keys of value would need to be cleaned when they are arrays and for the key |
So should I spend more time on this to get also the nested filed ordering to work @alanpoulain or should I close it of the other PR is a prefered solution and should be extented for OrderFilter ? |
IMO, since it's a GraphQL-related issue, this solution is better. |
I've added a naive workaround so ordering on nesting property value would work now. |
I wonder if it's possible to use nested property filters like: |
@IonBazan I don't know much about the graphQL part yet, but at least the solution is the same for all filters used in graphQL context without changing the way it works for standard Rest API, that's why I went with that. |
I do understand that for people using GraphQL only, it might be tricky to define filters using the dot notation and use and underscored notation when using it but I don't really see any other better solution for now... |
{ | ||
$filters = $args; | ||
foreach ($filters as $name => &$value) { | ||
if ($name === $this->orderParameterName && \is_array($value)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not generalizing it for all filters (i.e. only verifying if $value
is an array)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My first idea was that this is not necessary fo all filters (like DateFilter) for example and wanted to keep the modification as small as possible... but on a second thought, I don't see any issue in generalizing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it simplifies the code 😉
features/graphql/filters.feature
Outdated
When I add "Accept" header equal to "application/hal+json" | ||
And I send a "GET" request to "/dummies?relatedDummies.name=RelatedDummy31" | ||
Then the response status code should be 200 | ||
And the response should be in JSON |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test shouldn't be here.
features/graphql/filters.feature
Outdated
When I send the following GraphQL request: | ||
""" | ||
{ | ||
dummies(order:{relatedDummy_name: "DESC"}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a space after order:
.
src/GraphQl/Type/SchemaBuilder.php
Outdated
{ | ||
foreach ($args as $key => $value) { | ||
if ($normalizeKeys && (strpos($key, '.'))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same, why not generalizing it?
Maybe we could use another character than the underscore to avoid confusion? |
@alanpoulain I would go for |
Seems fine to me. I think there is no BC break for now because GraphQL is treated as an experimental feature. It's not really clear enough for end-users though. |
@alanpoulain actually it would be a BC break for REST. Currently, nested property filters are built like: |
I think I get it. You want to avoid characters replacement by having the same kind of notation for the REST part and the GraphQL one? |
@alanpoulain Exactly, but I'm not sure if there are any drawbacks of this solution. This would require a total filters refactor and a lot of testing. I think the solution proposed by @antograssiot is good enough for now. |
80e8b17
to
94e66e8
Compare
features/graphql/filters.feature
Outdated
Scenario: Retrieve a collection filtered using the related search filter | ||
Given there are 1 dummy objects having each 2 relatedDummies | ||
And there are 1 dummy objects having each 3 relatedDummies | ||
When I add "Accept" header equal to "application/hal+json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it shouldn't be here as we are testing GraphQL endpoint, not HAL.
fee0d3f
to
08f169d
Compare
all comments so far have been addressed. |
src/GraphQl/Type/SchemaBuilder.php
Outdated
@@ -292,6 +292,9 @@ private function mergeFilterArgs(array $args, array $parsed, ResourceMetadata $r | |||
private function convertFilterArgsToTypes(array $args): array | |||
{ | |||
foreach ($args as $key => $value) { | |||
if (strpos($key, '.')) { | |||
$args[str_replace('.', '_', $key)] = $value; | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a line break after.
@@ -164,4 +164,22 @@ private function getSubresource(string $rootClass, array $rootResolvedFields, ar | |||
'collection' => $isCollection, | |||
]); | |||
} | |||
|
|||
private function getNormalizedFilters($args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add :array
at the end and array
for the parameter.
private function getNormalizedFilters($args) | ||
{ | ||
$filters = $args; | ||
foreach ($filters as $name => &$value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use references.
} | ||
|
||
if (strpos($name, '_')) { | ||
// Gives a chance to relations/nested fields |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a final point.
08f169d
to
38b383a
Compare
done @alanpoulain |
src/GraphQl/Type/SchemaBuilder.php
Outdated
@@ -292,6 +292,11 @@ private function mergeFilterArgs(array $args, array $parsed, ResourceMetadata $r | |||
private function convertFilterArgsToTypes(array $args): array | |||
{ | |||
foreach ($args as $key => $value) { | |||
if (strpos($key, '.')) { | |||
// Declare relations/nested fields in a GraphQL compatible syntax. | |||
$args[str_replace('.', '_', $key)] = $value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really working? Because we are not looping with the added value.
38b383a
to
78457bb
Compare
Good one, thank you very much @antograssiot. Can you also open a doc PR? It looks important to have this mentioned in the documentation PR (especially for REST actually). |
Sure, I'll prepare a doc update this weekend or next week @dunglas |
* Allow GraphQL to filter on nested property fixes api-platform#1714, api-platform#1867 * Allow ordering on nested property values
* Allow GraphQL to filter on nested property fixes api-platform#1714, api-platform#1867 * Allow ordering on nested property values
Possible replacement for #1743 without updating the filter but just the way filters are passed to the data provider.
ping @alanpoulain @IonBazan