carrooi/doctrine-queries

基于 kdyby/doctrine 的 doctrine 查询构建器构建器

1.2.1 2016-05-20 14:09 UTC

This package is auto-updated.

Last update: 2024-09-06 03:11:20 UTC


README

Build Status Donate

基于 kdyby/doctrine 的 doctrine 查询构建器构建器

安装

$ composer require carrooi/doctrine-queries

查询对象

请首先阅读 kdyby 的 查询对象 文档。

class UserQuery extends Carrooi\Doctrine\Queries\QueryObject
{

	public function byId($id)
	{
		$this->addFilter(function(QueryBuilder $qb) use ($id) {
			$qb->andWhere('u.id = :id')->setParameter('id', $id);
		});
		
		return $this;
	}
	
	public function doCreateQuery(Queryable $repository)
	{
		$qb = $repository->createQueryBuilder()
			->select('u')->from('App\User', 'u');
			
		$this
			->applyFilters($qb)
			->applySelectFilters($qb);
			
		// or just:
		// $this->applyAllFilters($qb);
		
		return $qb;
	}

}

选择过滤器

class UserQuery extends Carrooi\Doctrine\Queries\QueryObject
{

	public function selectCount()
	{
		$this->addSelectFilter(function(QueryBuilder $qb) {
			$qb->select('COUNT(u)');
		});
		
		return $this;
	}

}

选择

如果您有更多选择不同列的方法,您将遇到关于已选择列的错误。您可以通过使用一些辅助方法来避免这种情况。

class UserQuery extends Carrooi\Doctrine\Queries\QueryObject
{

	public function selectNick()
	{
		$this->trySelect('u', ['nick']);
		return $this;
	}
	
	public function selectEmail()
	{
		$this->trySelect('u', ['email']);
		return $this;
	}

}

DQL: SELECT PARTIAL u.{id,nick,email} FROM ...

带有结果别名

class UserQuery extends Carrooi\Doctrine\Queries\QueryObject
{

	public function selectNickAndEmail()
	{
		$this->trySelect('u', ['user' => ['nick', 'email']]);
		return $this;
	}

}

DQL: SELECT PARTIAL u.{id,nick,email} AS user FROM ...

或使用 distinct

class UserQuery extends Carrooi\Doctrine\Queries\QueryObject
{

	public function selectNick()
	{
		$this->tryDistinctSelect('u', ['nick']);
		return $this;
	}

}

您还可以使用经典列选择而没有部分选择。例如,这对于数组注入可能很有用。

class UserQuery extends Carrooi\Doctrine\Queries\QueryObject
{

	public function selectNick()
	{
		$this->trySelect('u', [
			'nick' => 'nickAlias',				// nickAlias will be name of result key
		]);
		return $this;
	}
	
	public function selectEmail()
	{
		$this->trySelect('u', ['email']); 		// you can combine partial and classic column selects
		return $this;
	}

}

DQL: SELECT u.nick AS nickAlias, PARTIAL u.{id,email} FROM ...

连接

与选择类似的问题也出现在连接上。如果您尝试多次连接相同的关系,您将得到错误。同样,为此有方法。

class UserQuery extends Carrooi\Doctrine\Queries\QueryObject
{

	public function byBookName($name)
	{
		$this->tryJoin('u.books', 'b');		// INNER JOIN
		
		$this->addFilter(function(QueryBuilder $qb) use ($name) {
			$qb->andWhere('b.name = :name')->setParameter('name', $name);
		});
		
		return $this;
	}

}

您还可以使用 tryLeftJoin 方法。

辅助方法

  • $query->addParameters(QueryBuilder $qb, array $parameters): 设置参数而不覆盖旧的参数

嵌套树搜索

如果您使用例如 gedmo 嵌套树,您还可以使用 TNestedTreeQuery 特性进行简单的树搜索。

class UserQuery extends Carrooi\Doctrine\Queries\QueryObject
{

	use Carrooi\Doctrine\Queries\Tree\TNestedTreeQuery;
	
	public function byTree(array $entities)
	{
		// ... some joins
		
		$this->addFilter(function(QueryBuilder $qb) use ($entities) {
			$condition = $this->createNestedTreeSearchCondition($entities, 'entityAlias');
			
			$qb->andWhere($condition->getCondition());
            $query->addParameters($qb, $condition->getParameters());
		});
	}

}

以下示例将找到数据库中至少有一个实体来自给定实体数组的所有实体,即使它们是相同的,也在某些子实体或某些父实体中。

按至少一个实体搜索(使用 OR) 默认

use Carrooi\Doctrine\Queries\Tree\SearchType;

$query->createNestedTreeSearchCondition($entities, 'entityAlias', SearchType::CONDITION_OR);

按所有实体搜索(使用 AND)

use Carrooi\Doctrine\Queries\Tree\SearchType;

$query->createNestedTreeSearchCondition($entities, 'entityAlias', SearchType::CONDITION_AND);

仅在父级和子级中搜索相同的实体 默认

use Carrooi\Doctrine\Queries\Tree\SearchType;

$query->createNestedTreeSearchCondition($entities, 'entityAlias', null, SearchType::SEARCH_EVERYWHERE);

仅搜索相同的实体

use Carrooi\Doctrine\Queries\Tree\SearchType;

$query->createNestedTreeSearchCondition($entities, 'entityAlias', null, SearchType::SEARCH_FOR_SAME);

仅在父级中搜索

use Carrooi\Doctrine\Queries\Tree\SearchType;

$query->createNestedTreeSearchCondition($entities, 'entityAlias', null, SearchType::SEARCH_IN_PARENTS);

仅在子级中搜索

use Carrooi\Doctrine\Queries\Tree\SearchType;

$query->createNestedTreeSearchCondition($entities, 'entityAlias', null, SearchType::SEARCH_IN_CHILDREN);

组合搜索

use Carrooi\Doctrine\Queries\Tree\SearchType;

$query->createNestedTreeSearchCondition($entities, 'entityAlias', null, SearchType::SEARCH_IN_PARENTS | SearchType::SEARCH_IN_CHILDREN);

自定义列名

TNestedTreeQuery 特性将默认使用这些列名

  • id
  • level
  • root
  • left
  • right

但如果您需要,您可以使用自定义名称

use Carrooi\Doctrine\Queries\Tree\SearchType;

$query->createNestedTreeSearchCondition($entities, 'entityAlias', null, null, [
	'id' => 'id',
	'level' => 'lvl',
	'root' => 'root',
	'left' => 'lft',
	'right' => 'rgt',
]);

获取结果

  • getQueryBuilder()
  • getResultSet()
  • getResult()
  • getPairs()
  • getOneOrNullResult()
  • getSingleScalarResult()

变更日志

  • 1.2.1

    • 更改依赖项
  • 1.2.0

    • 改进树搜索 DQL 的别名
    • 支持经典自定义列选择(不仅仅是部分选择)
    • 添加设置部分选择结果别名的选项
  • 1.1.0

    • 添加 DQL 字段函数
    • 添加 TNestedTreeQuery 特性以在嵌套树中进行搜索
  • 1.0.1

    • 不要重写现有的连接
  • 1.0.0

    • 初始版本