Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use API Platform filters in YAML?

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!

like image 824
Ajie62 Avatar asked Jun 27 '19 14:06

Ajie62


1 Answers

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

like image 161
Ajie62 Avatar answered Sep 24 '22 12:09

Ajie62