如何在partials中使用自定义DQL函数来水合查询结果。
寻找在createQuery或任何其他学说方式(nativeSql,QueryBuilder)中使用DQL函数的方法,它不需要使用partials但它应该根据表的关系来保持我的数组应该只选择选择性字段
以下查询工作正常:
$q = $em->createQuery("select "
. "partial t.{id, description}, "
. "partial ut.{id, firstName, lastName, email}, "
. "DATE_FORMAT(ut.created, '%m-%d-Y') "
. "from PMIUserBundle:Task t LEFT JOIN t.users ut");
DATE_FORMAT(ut.created,'%m-%d-Y')在偏出部分时工作正常。
DATE_FORMAT
已在config.yml
config.yml:
dql:
datetime_functions:
DATE_FORMAT: PMI\UserBundle\DoctrineFunctions\DateFormat
以下查询会产生问题:
$q = $em->createQuery("select "
. "partial t.{id, description}, "
. "partial ut.{id, firstName, lastName, email, DATE_FORMAT(created, '%m-%d-Y')}, "
. "DATE_FORMAT(ut.created, '%m-%d-Y') "
. "from PMIUserBundle:Task t LEFT JOIN t.users ut");
给出错误:
[Syntax Error] line 0, col 91: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_CURLY_BRACE, got '('
以下是我的DateFormat类:
class DateFormat extends \Doctrine\ORM\Query\AST\Functions\FunctionNode {
protected $dateExpression;
protected $formatChar;
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) {
return 'DATE_FORMAT('.
$sqlWalker->walkArithmeticExpression($this->dateExpression) .
','.
$sqlWalker->walkStringPrimary($this->formatChar).
')';
}
public function parse(\Doctrine\ORM\Query\Parser $parser) {
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->dateExpression = $parser->ArithmeticExpression();
$parser->match(Lexer::T_COMMA);
$this->formatChar = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
编辑:
好的,所以Partial不允许我使用DQL函数。感谢FuzzyTree解决方案在我的实体类中使用ut->getFormattedCreatedDate()
。但是我仍然很好奇如果我们将子表分组并使用mysql Aggregate函数计算一些数量。
如何使用createQuery,queryBuilder,nativeSQl或任何其他方式在doctrine2中实现以下条件:
每次如果我们使用DQL函数,我们是否必须像为DateFormat创建的那样创建类?如果我们使用嵌套的MySql函数,如
,该怎么办?GROUP_CONCAT(DISTINCT CONCAT(tags.id,',',tags.displayName)
感谢您阅读我的问题。
答案 0 :(得分:0)
如何在partials中使用自定义DQL函数来水合查询 结果
partial
关键字告诉doctrine返回仅部分水合的实体,并允许您指定要水合的字段。
在检索部分实体时,您只能选择实体的字段(因为否则会在哪里教授'存储您选择的字段?),所以它不可能将DQL函数指定为部分对象的字段。
答案 1 :(得分:0)
这个怎么样?
$qb = $this->_em->createQueryBuilder()
->select( 't.id, t.description, '
. 'ut.id, ut.firstName, '
. 'ut.lastName, ut.email, '
. 'DATE_FORMAT( ut.created, \'%m-%d-Y\' )' )
->from( 'PMIUserBundle:Task', 't' )
->leftjoin( 't.users', 'ut' );
$result = $qb->getQuery()->getResult();
假设您在Repository类中使用它(这就是为什么调用$ this-> _em)。
我注意到有关自定义功能的其他两件事:
希望这有帮助,
担
答案 2 :(得分:0)
PARTIAL ut.{id, firstName, lastName, email, DATE_FORMAT(created, '%m-%d-Y')}
在选择像这样的部分实体中使用DQL函数不支持。
它也没有多大意义。在这种情况下,您(可能)将字段created
映射为datetime
字段,因此您希望其中包含完整的DateTime
值。但现在你突然只使用了日期部分。而且情况变得更糟:您以某种方式格式化了值,无法创建DateTime
对象(它预期Y-m-d H:i:s
,而date
类型需要Y-m-d
)。
对于任何部分选择:不能,不应,更改字段的值。
您可以只使用数组,而不是保湿到部分实体。使用$q->getArrayResult()
或$q->getScalarResult()
,以更适合您的目的为准。
如果您愿意,可以将结果分组/嵌套在Repository方法中。例如:
public function getSomeData()
{
$result = array();
$dql = <<<EOQ
SELECT
t.id AS t_id,
t.description AS t_description,
u.id AS u_id,
u.firstName AS u_firstName,
u.lastName AS u_lastName,
u.email AS u_email,
DATE_FORMAT(u.created, '%m-%d-Y') AS u_created
FROM PMIUserBundle:Task t
LEFT JOIN t.users u
EOQ;
$q = $this->getEntityManager()->createQuery($dql);
foreach ($q->getScalarResult() as $row) {
if (!isset($result[$row['t_id']])) {
$result[$row['t_id']] = array(
'id' => $row['t_id'],
'description' => $row['t_description'],
'users' => array()
);
$result[$row['t_id']]['users'][] = array(
'u.id' => $row['u_id'],
'u.firstName' => $row['u_firstName'],
'u.lastName' => $row['u_lastName'],
'u.email' => $row['u_email'],
'u.created' => $row['u_created']
);
}
}
return $result;
}
嵌套DQL函数应该没问题(如果你正确编写它们)。并且DISTINCT
支持开箱即用。