问题描述
试图摆脱一些锈迹,并了解我将如何使用查询构建器来做到这一点!我尝试了几种方法,但遇到了各种神秘的错误。好久没有访问这种做事方式了,感谢帮助!
/**
* @ORM\Entity
* @ORM\Table(name="users")
*
class User {
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer",nullable=false,options={"unsigned"=true})
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="Group",cascade={"persist"})
*/
private $groups;
}
/**
* @ORM\Entity
* @ORM\Table(name="`groups`")
*
*/
class Group {
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer",options={"unsigned"=true})
*/
private $id;
}
现在,我还有一个单独的 GroupsCerts 类,它是特定组所需的认证列表。
/**
* @ORM\Entity
* @ORM\Table(name="groups_certs")
* This entity contains Meta data about group-certification relationship
*
*/
class GroupCertRecord
{
/**
* @var Group
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Group")
* @ORM\JoinColumn(onDelete="cascade")
*/
protected $group;
/**
* @var Certification
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Certification",inversedBy="group_records")
* @ORM\JoinColumn(onDelete="cascade")
*/
protected $cert;
/**
* @var \DateTime
* @ORM\Column(type="datetime",options={"default": "CURRENT_TIMESTAMP"})
*/
private $time_added;
}
简单的 sql
我目前很好地使用了 ResultSetMappingBuilder,使用该方法的 sql 的要点非常简单。例如,查找证书 3,sql 为:
SELECT U.*
FROM users U
WHERE U.id IN (
SELECT user_id
FROM users_groups UG
WHERE UG.group_id IN (
SELECT id
FROM groups G
WHERE G.id IN (
SELECT group_id
FROM groups_certs GC
WHERE GC.cert_id=3
)
)
)
我曾尝试将其映射到 QueryBuilder 表达式中,但它在“IN”的表达式构建器中消失了。它不喜欢我正在做的事情 - 快速解决?
我失败的尝试
$em = $this->getEntityManager();
$expr = $em->getExpressionBuilder();
$subQuery = $em->createqueryBuilder()
->select('(gc.group)')
->from(GroupCertRecord::class,'gc')
->where('gc.cert = :cert');
$queryD = $em->createqueryBuilder()
->select('u')
->from(User::class,'u')
->where($expr->in('u.groups',$subQuery->getDQL()))
->setParameter('cert',$cert);
谢谢!
解决方法
我相信您可以使用连接而不是子查询来实现相同的效果,并且纯 SQL 中的查询看起来像
select u.*
from users u
join users_groups ug on u.id = ug.user_id
join groups g on g.id = ug.group_id
join groups_certs gc on g.id = gc.group_id
join certification c on c.id = gc.cert_id
where c.id = 3
与子查询相比,这些连接查询在 DQL 或查询构建器中转换非常方便,在 DQL 中,您使用连接子句中的实体映射,其余原则将处理映射背后的表,如 {{1} } 指向与连接表的多对多关系,u.groups
将处理一对多映射等
除了您的问题之外,您几乎提供了所有必要的映射,除了 g.groupCertifications
与 Group
的关系我猜它会是这样的
GroupCertRecord
您的 DQL 看起来像
class Group
{
// ...
/**
* @ORM\OneToMany(targetEntity="GroupCertRecord",mappedBy="groups")
*/
private $groupCertifications;
}
查询构建将是
SELECT u
FROM AppBundle\Entity\User u
JOIN u.groups g
JOIN g.groupCertifications gc
JOIN gc.cert c
WHERE c.id = :id