自定义过滤器API平台不起作用

时间:2018-03-19 21:54:17

标签: api-platform.com

我正在尝试在API平台中实现自定义或过滤器。但由于某种原因,它没有加载。在下面找到我的配置。

这是我的过滤器:

<?php

namespace AppBundle\Filter;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use Doctrine\ORM\QueryBuilder;

use Doctrine\Common\Annotations\AnnotationReader;

final class SearchFilter extends AbstractFilter
{
    protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
    {
    if ($property === 'search') {
        $this->logger->info('Search for: ' . $value);
    } else {
        return;
    }

    $reader = new AnnotationReader();
    $annotation = $reader->getClassAnnotation(new \ReflectionClass(new $resourceClass), \AppBundle\Filter\SearchAnnotation::class);

    if (!$annotation) {
        throw new \HttpInvalidParamException('No Search implemented.');
    }

    $parameterName = $queryNameGenerator->generateParameterName($property);
    $search = [];
    $mappedJoins = [];

    foreach ($annotation->fields as $field)
    {
        $joins = explode(".", $field);
        for ($lastAlias = 'o', $i = 0, $num = count($joins); $i < $num; $i++) {
            $currentAlias = $joins[$i];
            if ($i === $num - 1) {
                $search[] = "LOWER({$lastAlias}.{$currentAlias}) LIKE LOWER(:{$parameterName})";
            } else {
                $join = "{$lastAlias}.{$currentAlias}";
                if (false === array_search($join, $mappedJoins)) {
                    $queryBuilder->leftJoin($join, $currentAlias);
                    $mappedJoins[] = $join;
                }
            }

            $lastAlias = $currentAlias;
        }
    }

    $queryBuilder->andWhere(implode(' OR ', $search));
    $queryBuilder->setParameter($parameterName, '%' . $value . '%');
}

/**
 * @param string $resourceClass
 * @return array
 */
public function getDescription(string $resourceClass): array
{
    $reader = new AnnotationReader();
    $annotation = $reader->getClassAnnotation(new \ReflectionClass(new $resourceClass), \AppBundle\Filter\SearchAnnotation::class);

    $description['search'] = [
        'property' => 'search',
        'type' => 'string',
        'required' => false,
        'swagger' => ['description' => 'Filter on ' . implode(', ', $annotation->fields)],
    ];

    return $description;
}
}

在api_filters.yml:

driver.custom_search_filter:
    class: 'AppBundle\Filter\SearchFilter'
    autowire: true
    tags: [ { name: 'api_platform.filter' } ]

在我的注释文件中:

<?php

namespace AppBundle\Filter;

use Doctrine\Common\Annotations\Annotation;
use Doctrine\Common\Annotations\Annotation\Target;
use Doctrine\Common\Annotations\AnnotationException;

/**
 * @Annotation
 * @Target("CLASS")
 */
final class SearchAnnotation
{
    public $fields = [];

    /**
     * Constructor.
     *
     * @param array $data Key-value for properties to be defined in this class.
     * @throws AnnotationException
     */
    public function __construct(array $data)
    {
        if (!isset($data['value']) || !is_array($data['value'])) {
            throw new AnnotationException('Options must be a array of strings.');
        }

        foreach ($data['value'] as $key => $value) {
            if (is_string($value)) {
                $this->fields[] = $value;
            } else {
                throw new AnnotationException('Options must be a array of strings.');
            }
        }
    }
}

最后在我的实体中:

    /**
 * A driver that bring meals from hub to customer.
 *
 *
 * @ApiResource(
 *     attributes={
 *         "filters"={"driver.search_filter","driver.custom_search_filter"},
 *         "denormalization_context"={"groups"={"post_driver"}}
 *     }
 * )
 * @Searchable({"firstName"})
 *
 * @ORM\Entity
 * @ORM\Table(name="vendor_driver")
 */
class Driver
{

完全按照此处报道的问题: https://github.com/api-platform/core/issues/398

我没有收到任何错误,但过滤器根本无法正常工作。我在Swagger看到它。但是当我在Swagger中输入一个值时,db会返回所有实体。它永远不会达到filterProperty方法。

有没有人有想法?

2 个答案:

答案 0 :(得分:1)

我只是设法通过删除自动装配来实现这一点,例如

my.custom_search_filter:
    class: AppBundle\Filter\CustomSearchFilter
    arguments:
        - '@doctrine'
        - '@request_stack'
        - '@logger'
    tags: [ { name: 'api_platform.filter', id: 'search' } ]

希望有所帮助。

答案 1 :(得分:0)

您是否已将自定义过滤器导入到Driver实体中?在自定义过滤器和here的Regexp示例中,它们被显式导入其自定义过滤器,例如:

use AppBundle\Filter\SearchAnnotation as Searchable;

/**
 * @Searchable({"name", "description", "whatever"})
 */

class Product
{