如何在YAML中使用API​​平台过滤器?

时间:2019-06-27 14:54:59

标签: php api-platform.com symfony-4.3

首先,我想告诉您,我已经阅读了有关今天遇到的问题的文档,并且我也在StackOverflow和Google上进行了搜索,但是没有找到合适的解决方案。

为了实践起见,我正在使用Symfony 4和API平台构建客户关系管理API。我已经学到了很多有关API平台的知识,即使我可以使用批注进行资源配置,但我还是强迫自己使用YAML来了解更多信息。

因此,我有一个Customer资源,该资源具有几个属性: id firstname lastname emailAddress 公司 createdAt updatedAt 所有者。我的目标是在此资源上(在YAML中)添加 SearchFilter ,并将大多数属性添加为此过滤器的属性。

我已经尝试过此处给出的解决方案:https://github.com/api-platform/core/issues/1755。问题是我无法使其正常工作。在services.yaml中,我看到可以添加参数,但是我不知道可以在注释中找到什么等效项...

config/services.yaml中:

# filters
    app.my_filter:
        parent: 'api_platform.doctrine.orm.search_filter'
        tags: ['api_platform.filter']
        autowire: false
        autoconfigure: false
        public: false

resources/customer.yaml中:

App\Entity\Customer:
    collectionOperations:
        get:
            normalization_context:
                groups: ['Customer:Get']
            filters: ['app.my_filter']

我打算做的事情与此类似,src/Entity/Customer.php中带有注释:

/**
 * @ApiResource
 *
 * [...]
 *
 * @ApiFilter(SearchFilter::class, properties={
 *     "firstname": "partial",
 *     "lastname": "partial",
 *     "emailAddress": "partial",
 *     "company": "partial"
 * })
 */
class Customer
{
...
}

我希望您能够提供帮助,并且我的问题已得到明确解释。如果没有,请告诉我,我会尽力为您提供更多详细信息。

谢谢!

1 个答案:

答案 0 :(得分:1)

我找到了解决问题的方法。看来API平台文档离答案还不太远!在资源配置文件中尝试了一段时间之后,我最终决定给services.yaml文件一个机会。 on this github issue对我有很大帮助。所以,这就是我所做的。

步骤1-# 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 中:

autowire

注释0:这里需要autoconfigurevendor/api-platform/core/src/Swagger/Serializer/DocumentationNormalizer::getFilter()参数,否则会出现错误:

设置了“父”时,不能从“ _defaults”继承服务“ app.customer_resource.search_filter”上的属性“ autowire” /“ autoconfigure”。将您的子定义移动到单独的文件或在[...]中明确定义此属性(该属性已加载到资源“ [...]”中)。

注释1:我注意到这里最重要的元素是“ tags” 参数的“ id” 元素。在寻找解决方案时,我发现了config/resources/customer.yaml,这表明您必须提供一个过滤器ID才能起作用。在第二步中自己看看。

步骤2-在您的资源配置文件中(我的文件位于App\Entity\Customer: collectionOperations: get: filters: ['customer.search_filter'] # ... 中)

PRODUCTS ||= [
  [name: 'tennis_balls', description: 'you need em'],
  [name: 'racquets', description: 'have at least one'],
  [name: 'sneakers', description: 'run fast with these']
].freeze

class Product
  def self.by_name(name)
    PRODUCTS.flatten.find{|a| a[:name] == name.to_s}
  end

  def self.by_names(names)
    names.map{|name| by_name(name)}.compact
  end
end

我刚刚通过使用(如我所说的)重要过滤器ID添加了GET收集操作的过滤器。因此,这解决了我的问题。 但是,如果有人在那里有更好/更简单的解决方案,我很高兴知道。

Screenshot: What the API looks like when SearchFilter is in place