frankdejonge/doctrine-query-specification
最新稳定版本:0.4.0
Composer 安装命令:
composer require frankdejonge/doctrine-query-specification
包简介
Specification based querying for Doctrine2
README 文档
README
This packages eases the translation of domain questions to things doctrine can understand.
Query specifications allow you to hook into three stages of the query building process.
- Applying constraints
- Modifying the query builder.
- Modifying the query.
This allows you to encapsulate query logic in bite-sized, small, object. When naming these objects you can take into account what purpose they fulfill.
Installation:
composer require frankdejonge/doctrine-query-specification
Effect
Turn code like this:
// Get the newest 5 articles, needed for front-page $qb = $articleRepository->createQueryBuilder('a'); $query = $qb ->where($qb->expr()->eq('a.published', true)) ->getQuery() ->getResult();
Into this:
$articles = $articleRepositoryFieldEquals->findBySpecification(new FrontPageArticles());
Examples
Specification aware repositories.
use FrankDeJonge\DoctrineQuerySpecification\SpecificationAwareEntityRepository; use FrankDeJonge\DoctrineQuerySpecification\SpecificationAwareRepository; use FrankDeJonge\DoctrineQuerySpecification\SpecificationAwareRepositoryTrait; class ArticleRepository extends SpecificationAwareEntityRepository { } // OR class ArticleRepository implements SpecificationAwareRepository { use SpecificationAwareRepositoryTrait; }
Query constraints.
<?php use Doctrine\ORM\QueryBuilder; use FrankDeJonge\DoctrineQuerySpecification\QueryConstraint; class IsPublished implements QueryConstraint { public function asQueryConstraint(QueryBuilder $builder, string $rootAlias): ?object { $expr = $builder->expr(); return $expr->eq("{$rootAlias}.published", true); } } $publishedArticles = $articleRepository->findBySpecification(new IsPublished);
Query constrains can also accept user-provided input in constructors. When doing so, use parameterized queries to protect yourself against SQL-injections.
<?php use Doctrine\ORM\QueryBuilder; use FrankDeJonge\DoctrineQuerySpecification\QueryConstraint; class ArticleHasNameLike implements QueryConstraint { /** @var string */ private $name; public function __construct(string $name) { $this->name = $name; } public function asQueryConstraint(QueryBuilder $builder, string $rootAlias): ?object { $expr = $builder->expr(); $builder->setParameter('name_search', $this->name); return $expr->like("{$rootAlias}.name", ':name_search'); } } $publishedArticles = $articleRepository->findBySpecification(new ArticleHasNameLike('Awesome Name'));
Query modifiers.
<?php use Doctrine\ORM\Query; use FrankDeJonge\DoctrineQuerySpecification\QueryModifier; class AsArray implements QueryModifier { public function modifyQuery(Query $query, string $rootAlias): void { $query->setHydrationMode(Query::HYDRATE_ARRAY); } } $publishedArticles = $articleRepository->findBySpecification(new AsArray);
QueryBuilder modifiers.
<?php use Doctrine\ORM\QueryBuilder; use FrankDeJonge\DoctrineQuerySpecification\QueryBuilderModifier; class InReverseOrder implements QueryBuilderModifier { public function modifyQueryBuilder(QueryBuilder $builder, string $rootAlias): void { $builder->orderBy("{$rootAlias}.id", "DESC"); } } $publishedArticles = $articleRepository->findBySpecification(new InReverseOrder);
Specification composition
There are three ways of building compositions. Firstly there are specification collections
which allow you to create andX and orX groups.
$andSpecification = SpecificationCollection::all( new IsPublished(), new InReversedOrder(), new WithAuthor(), ); $orSpecification = SpecificationCollection::any( new IsFeatured(), new IsPublishedToday(), );
The second way is to create new specification objects which encapsulate one of more other specifications.
<?php use Doctrine\ORM\QueryBuilder; use FrankDeJonge\DoctrineQuerySpecification\QueryConstraint; class FeaturedFromAuthor implements QueryConstraint { public function __construct(Author $author) { $this->author = $author; } public function asQueryConstraint(QueryBuilder $queryBuilder, string $rootAlias): ?object { $expr = $queryBuilder->expr(); return $expr->andX( (new FromAuthor($this->author))->asQueryConstraint($queryBuilder, $rootAlias), (new FeaturedArticle)->asQueryConstraint($queryBuilder, $rootAlias), ); } }
Lastly you can extend a generic collection:
<?php use FrankDeJonge\DoctrineQuerySpecification\SpecificationCollection\All; class FeaturedFromAuthor extends All { public function __construct(Author $author) { parent::__construct( new FromAuthor($author), new FeaturedArticle(), ); } }
统计信息
- 总下载量: 54.93k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 75
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2019-11-10