Symfony表单查询生成器和实体存储库

16
我想创建一个表单,其数据类型基于当前登录的用户的集合类型。我正在遵循Symfony cookbook中这个章节。当query_builder选项是闭包函数并从DQL获取数据时,一切正常。由于需要从代码的不同位置获取数据,我更喜欢在Repository类中定义查询。这是我的Repository中的函数:
public function findOwnedBy($user) {
    $query = $this->getEntityManager()->createQuery("SELECT l FROM MyBundle:Article a JOIN a.owndBy u WHERE u.id = :userId");
    $query->setParameters(array("userId"=>$user->getId()));
    return $query->getResult();
}

这个函数在控制器中调用时会返回一系列文章的数组。以下是Symfony文档的片段:

$formOptions = array(
                    'class' => 'Acme\DemoBundle\Entity\User',
                    'multiple' => false,
                    'expanded' => false,
                    'property' => 'fullName',
                    'query_builder' => function(EntityRepository $er) use ($user) {
                        // build a custom query, or call a method on your repository (even better!)
                    },
                );
当我在query_builder中调用我的Repository函数时,我会得到一个错误:期望类型为“Doctrine\ORM\QueryBuilder”的参数,“给定数组”。我理解这个错误,因为我的Repository返回一个Entity数组,而不是QueryBuilder。
我不想复制代码并在表单中创建新的QueryBuilder。如何最好地使用Repository中的查询?我考虑在Repository中有两个函数,一个返回数组,另一个返回QueryBuilder。但Symfony文档中的注释"或者在你的repository上调用一个方法(更好的方法!)"让我认为还有更好的方法处理这种情况。
2个回答

28

这很简单。按照以下步骤操作:

public function queryOwnedBy($user) {

    $query = $this->createQueryBuilder('a')
            ->from('MyBundle:Article', 'a')
            ->innerJoin('a.owndBy', 'u')
            ->where('u.id = :id')                
            ->setParameter('id', $user->getId());

    return $query;
}

public function findOwnedBy($user) {
    return $this->queryOwnedBy($user)
            ->getQuery()
            ->getResult();
}

然后在表单构建器中:

$formOptions = array(
    'class' => 'Acme\DemoBundle\Entity\User',
    'multiple' => false,
    'expanded' => false,
    'property' => 'fullName',
    'query_builder' => function(EntityRepository $er) use ($user) {
        return $er->queryOwnedBy($user);
    },
);

编辑

感谢ncatnow和unagi,我已将之前的函数更改为返回查询构建器。


我也认为这应该很容易,这是我的第一次尝试。但是它返回了错误“预期类型为“Doctrine\ORM\QueryBuilder”的参数,“给定数组”。似乎query_builder需要一个 QueryBuilder 对象,无论是直接给出还是由闭包返回。 - Florent
修改了帖子。创建两个函数,一个返回查询,另一个返回结果。在表单构建器中调用返回查询的函数。这样就可以实现DRY。抱歉,我会更改名称,因为它们不合适。 - saamorim
呵呵,这确实是我在问题的最后一段所描述并实际执行的。我会按照那种方式去做,Symfony文档中的小注释让人觉得它可以直接使用,有点令人困惑;) - Florent
@Florent 是的,抱歉,没有注意到最后一段话。 - saamorim
7
请注意,上面的示例代码仍然不正确 - 它返回了一个Query而不是QueryBuilder,因此会失败。 - ncatnow
显示剩余2条评论

8

我对saamorim的回答进行了一点小修正。正确的代码应该是这样的:

public function queryOwnedBy($user) {

    $query = $this->createQueryBuilder("u")
            ->where('u.id = :id')                
            ->setParameter('id', $user->getId());

    return $query;
}

public function findOwnedBy($user) {
    return $this->queryOwnedBy($user)
            ->getQuery()
            ->getResult();
}

谢谢。我已经将您的答案集成到我的帖子中,并根据示例更改了查询。 - saamorim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接