【问题标题】:How to inject api-plaform's pagination filter on my custom dataprovider如何在我的自定义数据提供者上注入 api-plaform 的分页过滤器
【发布时间】:2019-07-13 10:33:31
【问题描述】:

我正在使用 symfony4 开发一个应用程序,其中我使用的是 api-platform。我为特定实体(例如汽车)创建了一个自定义数据提供程序。 CarCollectionDataProvider 返回所有蓝色汽车。

<?php

namespace App\DataProvider;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator;
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use App\Entity\Car;
use Doctrine\Common\Persistence\ManagerRegistry;
use Generator;

final class CarCollectionDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface
{
    private $managerRegistry;
    private $paginationExtenstion;

    public function __construct(ManagerRegistry $managerRegistry, PaginationExtension $paginationExtension)
    {
        $this->managerRegistry = $managerRegistry;
        $this->paginationExtenstion = $paginationExtension;
    }

    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
    {
        return Car::class === $resourceClass;
    }

    public function getCollection(string $resourceClass, string $operationName = null): Generator
    {
        $queryBuilder = $this->managerRegistry
            ->getManagerForClass($resourceClass)
            ->getRepository($resourceClass)->createQueryBuilder('car')
            ->where('car.color = :color')
            ->setParameter('color', 'blue');

        $this->paginationExtenstion->applyToCollection($queryBuilder, new QueryNameGenerator(), $resourceClass, $operationName, []);

        yield $this->paginationExtenstion->getResult($queryBuilder, $resourceClass, $operationName, []);
    }
}

如何在我的自定义数据提供者 (CarCollectionDataProvider) 上注入 api-platform 的分页扩展?

【问题讨论】:

  • 问题已更新

标签: symfony dataprovider api-platform.com


【解决方案1】:

这对我来说很好用:

<?php

namespace App\DataProvider;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator;
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use App\Entity\Car;
use Doctrine\Common\Persistence\ManagerRegistry;

final class CarCollectionDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface
{
    private $managerRegistry;
    private $paginationExtension;
    private $context;

    public function __construct(ManagerRegistry $managerRegistry, PaginationExtension $paginationExtension)
    {
        $this->managerRegistry = $managerRegistry;
        $this->paginationExtension = $paginationExtension;
    }

    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
    {
        $this->context = $context;
        return Car::class === $resourceClass;
    }

    public function getCollection(string $resourceClass, string $operationName = null)
    {

        $queryBuilder = $this->managerRegistry
            ->getManagerForClass($resourceClass)
            ->getRepository($resourceClass)->createQueryBuilder('car')
            ->where('car.color = :color')
            ->setParameter('color', 'blue');

        $this->paginationExtension->applyToCollection($queryBuilder, new QueryNameGenerator(), $resourceClass, $operationName, $this->context);

        if ($this->paginationExtension instanceof QueryResultCollectionExtensionInterface
            && $this->paginationExtension->supportsResult($resourceClass, $operationName, $this->context)) {

            return $this->paginationExtension->getResult($queryBuilder, $resourceClass, $operationName, $this->context);
        }

        return $queryBuilder->getQuery()->getResult();

    }
}

【讨论】:

    【解决方案2】:

    如果你想要的只是在一些资源的所有收集操作的查询中添加一个像 ->where('car.color = :color') 这样的标准,自定义扩展更合适,并且可以使用默认分页(和过滤器):

    // api/src/Doctrine/CarCollectionExtension.php
    
    namespace App\Doctrine;
    
    use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
    use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
    use App\Entity\Car;
    use Doctrine\ORM\QueryBuilder;
    
    final class CarCollectionExtension implements QueryCollectionExtensionInterface
    {
        public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null): void
        {
            if ($resourceClass != Car::class) return;
    
             $rootAlias = $queryBuilder->getRootAliases()[0];
             $queryBuilder->andWhere($rootAlias. '.color = :color');
             $queryBuilder->setParameter('color', 'blue');
        }
    }
    

    您可以通过在 if 语句中添加如下内容来使此扩展特定于某个操作:

    || $operationName == 'get_blue'
    

    (from the docs) 如果你不使用自动配置,你必须注册自定义扩展:

    # api/config/services.yaml
    services:
    
        # ...
    
        'App\Doctrine\CarCollectionExtension':
            tags:
                - { name: api_platform.doctrine.orm.query_extension.collection }
    

    如果您还想为项目操作添加标准,请参阅the docs on Extensions

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-21
      • 2014-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 2018-06-14
      相关资源
      最近更新 更多