opwoco/query-filter-bundle

在您的Symfony 4应用中(使用Doctrine2作为ORM)轻松过滤请求的方法。

安装: 4

依赖者: 0

建议者: 0

安全: 0

星标: 0

关注者: 1

分支: 8

类型:symfony-bundle

1.1.1 2019-07-24 13:42 UTC

This package is not auto-updated.

Last update: 2024-09-13 12:58:16 UTC


README

Query Filter Bundle

Query Filter Bundle将请求过滤和分页功能引入使用Doctrine 2的Symfony 4应用程序。

安装

首先,安装依赖项

$ composer require artprima/query-filter-bundle

使用示例

基本示例

  • 控制器
<?php

namespace App\Controller;

use Artprima\QueryFilterBundle\QueryFilter\Config\BaseConfig; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Artprima\QueryFilterBundle\Request\Request;
use Artprima\QueryFilterBundle\QueryFilter\QueryFilter;
use Artprima\QueryFilterBundle\Response\Response;
use App\Repository\ItemRepository;

class DefaultController extends Controller
{
    // ...
    
    /**
     * @Route("/") 
     */
    public function indexAction(HttpRequest $request, ItemRepository $repository)
    {
        // set up the config
        $config = new BaseConfig();
        $config->setSearchAllowedCols(['t.name']);
        $config->setAllowedLimits([10, 25, 50, 100]);
        $config->setDefaultLimit(10);
        $config->setSortCols(['t.id'], ['t.id' => 'asc']);
        $config->setRequest(new Request($request));
        
        // here we provide a repository callback that will be used internally in the QueryFilter
        // The signature of the method must be as follows: function functionName(QueryFilterArgs $args): QueryResult;
        $config->setRepositoryCallback([$repository, 'findByOrderBy']);
        
        // Response must implement Artprima\QueryFilterBundle\Response\ResponseInterface
        $queryFilter = new QueryFilter(Response::class);
        /** @var Response $data the type of the variable is defined by the class in the first argument of QueryFilter's constructor */
        $response = $queryFilter->getData($config);
        $data = $response->getData();
        $meta = $response->getMeta();
        
        // ... now do something with $data or $meta
    }
    
    // ...
}
  • 仓库
<?php

namespace App\Repository;

use App\Entity\Item;
use Artprima\QueryFilterBundle\Query\Mysql\PaginationWalker;
use Artprima\QueryFilterBundle\Query\ConditionManager;
use Artprima\QueryFilterBundle\Query\ProxyQueryBuilder;
use Artprima\QueryFilterBundle\QueryFilter\QueryFilterArgs;
use Artprima\QueryFilterBundle\QueryFilter\QueryResult;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;

class ItemRepository extends ServiceEntityRepository
{
    /**
     * @var ConditionManager
     */
    private $pqbManager;

    public function __construct(RegistryInterface $registry, ConditionManager $manager)
    {
        parent::__construct($registry, Item::class);
        $this->pqbManager = $manager;
    }

    
    public function findByOrderBy(QueryFilterArgs $args): QueryResult
    {
        // Build our request
        $qb = $this->createQueryBuilder('t')
            ->setFirstResult($args->getOffset())
            ->setMaxResults($args->getLimit());

        $proxyQb = new ProxyQueryBuilder($qb, $this->pqbManager);
        $qb = $proxyQb->getSortedAndFilteredQueryBuilder($args->getSearchBy(), $args->getSortBy());
        $query = $qb->getQuery();
        $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, PaginationWalker::class);
        $query->setHint("mysqlWalker.sqlCalcFoundRows", true);
        $result = $query->getResult();
        $totalRows = $this->_em->getConnection()->query('SELECT FOUND_ROWS()')->fetchColumn();
        
        // return the wrapped result
        return new QueryResult($result, $totalRows);
    }    
    
    // ...
}

现在您可以启动PHP服务器并过滤请求

GET http://127.0.0.1:8000/?filter[t.name]=Doe&limit=100

此请求将在DQL中执行LIKE请求

SELECT t FROM Item WHERE t.name LIKE "%Doe%" LIMIT 100

高级示例

此过滤库最好与JMSSerializerBundle和FOSRestBundle一起使用。您最终将编写的代码将比基本示例中展示的少得多。

要利用高级使用,安装所有包。

composer require friendsofsymfony/rest-bundle
composer require jms/serializer-bundle
composer require artprima/query-filter-bundle
  • config/bundles.php中启用它们
<?php

return [
    // ...
    Artprima\QueryFilterBundle\ArtprimaQueryFilterBundle::class => ['all' => true],
    FOS\RestBundle\FOSRestBundle::class => ['all' => true],
    JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
    // ...
];

注意:您可能需要根据您的设置添加更多的包,例如FOSRestBundle和/或JMSSerializerBundle。

  • 控制器
<?php

namespace App\Controller;

use App\QueryFilter\Response;
use App\Repository\ItemRepository;
use Artprima\QueryFilterBundle\QueryFilter\Config\ConfigInterface as QueryFilterConfigInterface;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Routing\ClassResourceInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Artprima\QueryFilterBundle\Controller\Annotations\QueryFilter;

class ItemController extends FOSRestController implements ClassResourceInterface
{
    /**
     * @Rest\View(serializerEnableMaxDepthChecks=true)
     * @ParamConverter("config", class="App\QueryFilter\Config\ItemConfig",
     *                           converter="query_filter_config_converter",
     *                           options={"entity_class": "App\Entity\Item", "repository_method": "findByOrderBy"})
     * @QueryFilter()
     * @Rest\Get("/items")
     */
    public function cgetAction(QueryFilterConfigInterface $config)
    {
        return $config;
    }
}
  • 仓库
<?php

namespace App\Repository;

use App\Entity\Item;
use Artprima\QueryFilterBundle\Query\Mysql\PaginationWalker;
use Artprima\QueryFilterBundle\Query\ConditionManager;
use Artprima\QueryFilterBundle\Query\ProxyQueryBuilder;
use Artprima\QueryFilterBundle\QueryFilter\QueryFilterArgs;
use Artprima\QueryFilterBundle\QueryFilter\QueryResult;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;

/**
 * @method Item|null find($id, $lockMode = null, $lockVersion = null)
 * @method Item|null findOneBy(array $criteria, array $orderBy = null)
 * @method Item[]    findAll()
 * @method Item[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class ItemRepository extends ServiceEntityRepository
{
    /**
     * @var ConditionManager
     */
    private $pqbManager;

    public function __construct(RegistryInterface $registry, ConditionManager $manager)
    {
        parent::__construct($registry, Item::class);
        $this->pqbManager = $manager;
    }

    public function findByOrderBy(QueryFilterArgs $args): QueryResult
    {
        $qb = $this->createQueryBuilder('t')
            ->setFirstResult($args->getOffset())
            ->setMaxResults($args->getLimit());

        $proxyQb = new ProxyQueryBuilder($qb, $this->pqbManager);
        $qb = $proxyQb->getSortedAndFilteredQueryBuilder($args->getSearchBy(), $args->getSortBy());
        $query = $qb->getQuery();
        $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, PaginationWalker::class);
        $query->setHint("mysqlWalker.sqlCalcFoundRows", true);
        $result = $query->getResult();
        $totalRows = $this->_em->getConnection()->query('SELECT FOUND_ROWS()')->fetchColumn();

        return new QueryResult($result, $totalRows);
    }
}

ItemConfig

<?php

namespace App\QueryFilter\Config;

use Artprima\QueryFilterBundle\QueryFilter\Config\BaseConfig;

class ItemConfig extends BaseConfig
{
    public function __construct()
    {
        $this->setSearchAllowedCols(array(
            't.name',
        ));

        $this->setSortCols(
            array(
                't.id',
            ),
            array('t.id' => 'desc') // default
        );
    }
}

简单查询过滤示例

注意:假设所有使用的字段都在配置中启用

高级查询过滤示例

简单模式对于大多数情况已经足够,但是有时我们可能需要构建更复杂的过滤器,其中一个字段被重复使用。

分页示例

排序示例

注意:目前此包不支持在 ORDER BY 中使用多个字段。

此文档尚未完成,将会有更多示例随后提供.

代码许可

您可以在 MIT 许可证的条款下自由使用此存储库中的代码。LICENSE 文件包含此许可的副本。