Doctrine QueryBuilder需要为leftJoin更改ON条件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Doctrine QueryBuilder需要为leftJoin更改ON条件相关的知识,希望对你有一定的参考价值。
当有on或condition时,我有左连接的本机sql查询,如何在查询生成器中表示它?
$query = " SELECT te.id
FROM task_executions AS te
INNER JOIN tasks AS t ON t.id = te.task_id
LEFT JOIN cost_objects AS co ON co.id = t.cost_object_id
LEFT JOIN cost_object_managers AS com ON com.cost_object_id = co.id OR com.cost_object_id = co.parent_id
我需要在查询生成器中表示它。但是在User
实体中我有ManyToMany关系,没有单独的表,当我尝试左连接WITH
条件时,这与我需要的不一样。我需要改变ON
的关系
LEFT JOIN cost_object_managers AS com ON com.cost_object_id = co.id OR com.cost_object_id = co.parent_id
用户实体
class User
{
...
/**
* @ORMManyToMany(targetEntity="CostObject", mappedBy="users")
*/
private $costObjects;
}
CostObject实体
class CostObject
{
/**
* @var CostObject
*
* @ORMManyToOne(targetEntity="CostObject", inversedBy="children")
* @ORMJoinColumns({
* @ORMJoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
* })
*/
private $parent;
/**
* @var ArrayCollection
*
* @ORMManyToMany(targetEntity="User", inversedBy="costObjects")
* @ORMJoinTable(name="cost_object_managers",
* joinColumns={@ORMJoinColumn(name="cost_object_id", referencedColumnName="id", onDelete="CASCADE")},
* inverseJoinColumns={@ORMJoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")}
* )
*/
private $users;
和我的查询生成器没有条件
$qb->select('te')
->from('AppBundle:TaskExecution', 'te')
->innerJoin('te.task', 't')
->leftJoin('t.costObject', 'co')
->leftJoin('co.users', 'com')
这是$query->getSQL()
SELECT some_name FROM task_executions t0_ INNER JOIN tasks t1_ ON t0_.task_id = t1_.id LEFT JOIN cost_objects c2_ ON t1_.cost_object_id = c2_.id LEFT JOIN cost_object_managers c4_ ON c2_.id = c4_.cost_object_id LEFT JOIN users u3_ ON u3_.id = c4_.user_id ORDER BY t0_.execution_start DESC
在这个例子中,我看到ON
关系条件LEFT JOIN users u3_ ON u3_.id = c4_.user_id
。并且需要像在本机sql中一样进行更改
我现在有
$qb->select('te')
->from('AppBundle:TaskExecution', 'te')
->innerJoin('te.task', 't')
->leftJoin('t.costObject', 'co')
->leftJoin(
'co.users',
'com',
Join::ON,
$qb->expr()->orX(
'co = com.costObjects',
'co.parent = com.costObjects'
)
)
但是得到了错误
[Syntax Error] line 0, col 112: Error: Expected end of string, got 'ON'
如果我使用WITH
条件,在我的sql表示我仍然有id的关系,我不需要那个
->leftJoin(
'co.users',
'com',
Join::WITH,
$qb->expr()->orX(
'co MEMBER OF com.costObjects',
'co.parent MEMBER OF com.costObjects'
)
)
LEFT JOIN users u3_ ON u3_.id = c4_.user_id AND (EXISTS (SELECT 1 FROM cost_object_managers c5_ INNER JOIN cost_objects c6_ ON c5_.cost_object_id = c6_.id WHERE c5_.user_id = u3_.id AND c6_.id IN (c2_.id)) OR EXISTS (SELECT 1 FROM cost_object_managers c5_ INNER JOIN cost_objects c6_ ON c5_.cost_object_id = c6_.id WHERE c5_.user_id = u3_.id AND c6_.id IN (c2_.parent_id)))
我的意思是users u3_ ON u3_.id = c4_.user_id AND
但在原生查询中我们只有LEFT JOIN cost_object_managers AS com ON com.cost_object_id = co.id OR com.cost_object_id = co.parent_id
如何使用ON
条件类型在Query Builder中重现?
如果您有查询并且它适用于您,则无需完成将其转换为DQL或QueryBuilder编程语法的所有工作。您可以使用Doctrine的Native Query,然后 - 如果需要 - 将结果映射到您的对象。只需创建一个自定义存储库,并在其中创建一个大致如下所示的新方法:
public function findTaskExecutionBy...()
{
$query = $this->entityManager->createNativeQuery('SELECT te.id FROM ...');
return $query->getSingleScalarResult(); // If it's just one id you expect
}
如果您希望返回多个id,也可以使用$query->getResult()
。或者,如果您想要整个Task-object,请使用ResultSetMapping:
$rsm = new ResultSetMappingBuilder($this->entityManager);
$rsm->addRootEntityFromClassMetadata('AppEntityTask', 'te');
$query = $this->entityManager->createNativeQuery(
'SELECT te.* FROM ...',
您还可以查看Doctrine文档以获取更详细的说明和更多示例:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html $ rsm);
以上是关于Doctrine QueryBuilder需要为leftJoin更改ON条件的主要内容,如果未能解决你的问题,请参考以下文章
Doctrine / Symfony:在使用 QueryBuilder 之前将自定义类型转换为数据库值
Doctrine preLoad Listener 在执行前操纵 QueryBuilder
Symfony 5,Doctrine queryBuilder OneToMany 关系
是否可以使用 Doctrine QueryBuilder 构建 INSERT INTO SELECT 查询?