在Symfony2中的表单类型中,我想包含一个带有查询构建器的实体字段,以便选择要显示的行。
我的查询很复杂,我无法找到一种方法来使用查询构建器,我想使用DQL。
不幸的是,我无法$repository->createQuery(...)
或$repository->getEntityManager()->createQuery()
。只有$repository->createQueryBuilder(...)
有效。
有办法解决这个问题吗?
public function buildForm(FormBuilderInterface $builder, array $options)
{
$user = $this->user;
$builder
->add('friend', 'entity',
array(
'class' => 'MyappUserBundle:User',
'label' => 'User',
'query_builder' => function(EntityRepository $repository) use ($user) {
$query = $repository->getEntityManager()->createQuery("
SELECT u
FROM MyappUserBundle:User u
WHERE
u.id NOT IN (SELECT friend FROM MyappUserBundle:Friendrequest WHERE user = :user)
AND
u.id NOT IN (SELECT user FROM MyappUserBundle:Friendrequest WHERE friend = :user)
AND
u.id != :user
")
->setParameter('user', $user)
;
return $query;
}
)
)
;
}
答案 0 :(得分:5)
如何解决query_builder
问题(以及一般问题)
我们知道我们可以访问您实体的EntityRepository
类。因此,我们可以轻松找到哪些方法可公开访问。
因此,我们可以在Google上搜索“doctrine api entityrepository”,它会引导我们the EntityRepository class API documentation on the doctrine site。
在该页面上,我们可以找到可公开访问的方法,您可以找到有关创建查询的3种方法,其中一种方法是createNativeNamedQuery
。
根据文档,此方法返回Doctrine\ORM\NativeQuery
的实例,单击它会导致另一个页面包含其他方法。您可以看到NativeQuery
具有setQuery
方法,并从Doctrine\ORM\AbstractQuery
继承了其他方法列表。
现在,我们可能拥有我们需要的所有信息,因此我们可以提出一个可能有效的解决方案(如果没有,那么我们可能真的非常接近)。
// The closure expects \Doctrine\ORM\QueryBuilder to be returned
// so we need to create a named query first then create a list of ids
// and pass it to a query builder.
'query_builder' => function(EntityRepository $repository) use ($user) {
// Query for user ids with sub queries
$results = $repository
->createNativeNamedQuery('u')
->setSQL("
SELECT u.id
FROM user AS u
WHERE u.id NOT IN (
SELECT friend FROM friend_request_table WHERE user = :user
)
AND u.id NOT IN (
SELECT user FROM friend_request_table WHERE friend = :user
)
AND u.id != :user
")
->setParameter('user', $user->getId())
->getArrayResult();
// Build an array of IDs
$ids = array_map(function ($row) {
return $row['id'];
}, $results);
// Returns a QueryBuilder
return $repository->createQueryBuilder('u')
->where('u.id IN (:ids)')
->setParameter('ids', $ids);
}
缺点是执行了两个查询。闭包期望返回QueryBuilder
,因此我们需要先创建一个原始查询,然后将结果传递给QueryBuilder
。
最重要的是,本机查询意味着原始SQL查询,因此您不能使用实体注释,并且不同数据库可能也不支持您的查询。
如果你喜欢我的观点,我认为你可以重构你的查询并删除子查询。删除子查询并将其结果作为参数传递将允许您使用DQL,因此支持更多类型的数据库。