edi*_*igu 5 orm dql doctrine-orm
我有以下 Doctrine 2 STI 车辆实体,该实体有两个名为“汽车”和“自行车”的子类,需要按车辆类型对车辆表中的项目进行计数。(例如;表格摘要:3 辆汽车、5 辆自行车..)
/**
* @ORM\Entity
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({"V" = "Vehicle", "C" = "CarEntity", "B" = "BikeEntity"})
* @ORM\Table(name="vehicles", uniqueConstraints={@ORM\UniqueConstraint(name="discr_type_name",columns={"type","name"})})
*/
class Vehicle {
...
}
Run Code Online (Sandbox Code Playgroud)
因此,我尝试执行以下 DQL 查询,但没有一个起作用:
SELECT v, TYPE(v) as vtype, count(v.id) as cnt FROM Vehicle v GROUP BY TYPE(v);
SELECT v, count(v.id) as cnt, TYPE(v) as vtype FROM Vehicle v GROUP BY vtype;
SELECT v, count(v.id) as cnt, TYPE(v) as vtype FROM Vehicle v GROUP BY TYPE(vtype);
Run Code Online (Sandbox Code Playgroud)
查询异常:
[Syntax Error] line 0, col 10: Error: Expected known function, got 'TYPE'
Run Code Online (Sandbox Code Playgroud)
另一个:
[Semantical Error] line 0, col 83 near 'TYPE()': Error: Cannot group by undefined identification or result variable
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?(学说版本为2.3)
您可以实现自己的 DQL 函数。网络上有一些可行的解决方案,例如: https: //gist.github.com/jasonhofer/8420677
我使用了该代码并对其进行了一些修改:
<?php
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\QueryException;
use Doctrine\ORM\Query\SqlWalker;
/**
* Provides a way to access an entity's discriminator field in DQL
* queries.
*
* Assuming the same "Person" entity from Doctrine's documentation on
* Inheritance Mapping, which has a discriminator field named "discr":
*
* Using the TYPE() function, DQL will interpret this:
*
* <pre>'SELECT TYPE(p) FROM Person p'</pre>
*
* as if you had written this:
*
* <pre>'SELECT p.discr FROM Person p'</pre>
*
* This conversion happens at the SQL level, so the ORM is no longer
* part of the picture at that point.
*
* Normally, if you try to access the discriminator field in a DQL
* Query, Doctrine will complain that the field does not exist on the
* entity. This makes sense from an ORM point-of-view, but having
* access to the discriminator field allows us to, for example:
*
* - get the type when we only have an ID
* - query within a subset of all the available types
*/
class TypeFunction extends FunctionNode
{
public string $dqlAlias;
/**
* @throws QueryException
*/
public function getSql(SqlWalker $sqlWalker): string
{
$qComp = $sqlWalker->getQueryComponent($this->dqlAlias);
/** @var ClassMetadataInfo $class */
$class = $qComp['metadata'];
$tableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $this->dqlAlias);
if (!isset($class->discriminatorColumn['name'])) {
throw QueryException::semanticalError(
'TYPE() only supports entities with a discriminator column.'
);
}
return $tableAlias.'.'.$class->discriminatorColumn['name'];
}
/**
* @throws QueryException
*/
public function parse(Parser $parser): void
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->dqlAlias = $parser->IdentificationVariable();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
Run Code Online (Sandbox Code Playgroud)
之后,您必须按照Doctrine 手册中的描述注册自定义函数。如果您使用 Symfony,请转到此处。
这使您能够选择鉴别器列的值并稍后在查询中使用它,并且适用于选择、排序和分组。
我的工作片段是这样的:
$queryBuilder
->select('COUNT(DISTINCT entity) AS count, TYPE(entity) AS type')
->groupBy('type')
;
Run Code Online (Sandbox Code Playgroud)
专业提示:如果您不想type在结果数据中包含 ,您可以使用SELECT TYPE(entity) AS HIDDEN type
| 归档时间: |
|
| 查看次数: |
837 次 |
| 最近记录: |