First of all, I want to inform you that I already read the docs about the problem I'm having today, and I also made a search on StackOverflow and Google, but didn't find a proper solution.
I am building a Customer Relationship Management API for practice sake with Symfony 4 and API Platform. I already learned a lot about API Platform, and even though I could have used annotations for resources configuration, I forced myself to use YAML in order to learn more about it.
So, I have a Customer resource which has several attributes: id, firstname, lastname, emailAddress, company, createdAt, updatedAt, and owner. My goal is to add a SearchFilter on this resource (in YAML) and add most of the attributes as properties of this filter.
I already tried the solution given here: https://github.com/api-platform/core/issues/1755. The problem is that I can't manage to make it work. In services.yaml, I see that you can add arguments, but I don't know what equivalent you can find in annotations...
In config/services.yaml
:
# filters
app.my_filter:
parent: 'api_platform.doctrine.orm.search_filter'
tags: ['api_platform.filter']
autowire: false
autoconfigure: false
public: false
In resources/customer.yaml
:
App\Entity\Customer:
collectionOperations:
get:
normalization_context:
groups: ['Customer:Get']
filters: ['app.my_filter']
What I intend to is something similar to this with annotations in src/Entity/Customer.php
:
/**
* @ApiResource
*
* [...]
*
* @ApiFilter(SearchFilter::class, properties={
* "firstname": "partial",
* "lastname": "partial",
* "emailAddress": "partial",
* "company": "partial"
* })
*/
class Customer
{
...
}
I hope that you'll be able to help and that my problem is clearly explained. If not, please tell me and I'll do my best to give your more details.
Thanks!
I found a solution to my problem. It appears the API Platform docs wasn't too far away from the answer after all! After trying for some time in the resource configuration file, I finally decided to give a chance to the services.yaml
file. I was greatly helped on this github issue. So, here's what I did.
Step 1 - In services.yaml
:
# filters
app.customer_resource.search_filter:
parent: 'api_platform.doctrine.orm.search_filter'
arguments: [ { 'firstname': 'partial', 'lastname': 'partial', 'emailAddress': 'partial', 'owner.emailAddress': 'exact' } ]
tags: [ { name: 'api_platform.filter', id: 'customer.search_filter' } ]
autowire: false # required, explained below
autoconfigure: false # required, explained below
Note 0: the autowire
and autoconfigure
arguments are required here, otherwise you'll get an error:
Attribute "autowire"/"autoconfigure" on service "app.customer_resource.search_filter" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly in [...] (which is loaded in resource "[...]").
Note 1: I noticed the most important element here is the "id" element of the "tags" argument. While I was looking for a solution, I discovered vendor/api-platform/core/src/Swagger/Serializer/DocumentationNormalizer::getFilter()
, which indicates you have to give a filter id in order to make it work. See for yourself in step 2.
Step 2 - In your resource config file (mine is in config/resources/customer.yaml
)
App\Entity\Customer:
collectionOperations:
get:
filters: ['customer.search_filter']
# ...
I just added the filter for the GET collection operation by using the (like I said) important filter ID. So, this fixes my issue. BUT if someone out there has a better/simpler solution, I'd be glad to know it.
Screenshot: What the API looks like when SearchFilter is in place
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With