如何在Twig模板中使用自定义存储库方法?

时间:2013-08-16 15:40:50

标签: symfony doctrine-orm twig

假设我有一个实体User和一个实体Book,并且它们都由User.bookId = Book.id加入(这标志着用户拥有某本书,关系类型为oneUserToManyBook)。

如果我现在想要使用Doctrine的DQL或QueryBuilder对所有Books执行性能友好的提取,User已阅读,那么在Symfony2 / Doctrine2 webapp中实现此功能的最佳方法是什么,所以我可以在Twig模板的User循环中使用它们吗?

枝条

{% for user in users %}
   {{ user.name|e }}
       {% for address in user.getAddressesByUserId(user.getId()) %}
           {{ address.city }}
       {% endfor %}
{% endfor %}

我看到两种方法,但两种方法都没有达到我的目标:

第一种方法

创建自定义存储库类BookRepository

public function getBooksOwnedByUser($user_id) {
    return $em->createQuery('SELECT b.title
                             FROM MyBundle\Entity\User u,
                                  MyBundle\Entity\Book b
                             WHERE u.book_id = b.id'
                             AND u.id = :user_id)
              ->setParameter('user_id', $user_id)
              ->getResult();
}

问题:工作正常,但我无法在我的Twig模板中调用getBooksOwnedByUser()(因为它不依赖于实体User,而是与它的存储库绑定,这是一个Doctrine\ORM\EntityRepository的子类。


第二种方法

执行与上述相同的查询 - 不在我的UserRepository中,而是直接在我的User实体类中。

问题:我可以在我的Twig模板中调用此方法,但我不能(也不应该)在我的EntityManager实体类中使用User

1 个答案:

答案 0 :(得分:2)

最好是建立从用户到书籍的关系。假设你已经建立了这种关系,你可以这样查询:

public function getBooksOwnedByUser($user_id) {
    return $em->createQuery('SELECT u, b
                            FROM MyBundle\Entity\User u
                            JOIN u.books b
                            WHERE  u.id = :user_id')
                        ->setParameter('user_id', $user_id)
                        ->getResult();
}

然后在你的控制器中:

$em = $this->getDoctrine()->getManager();
$user_with_books = $em->getRepository('MyBundle\Entity\User')
    ->getBooksOwnedByUser($user->getId());

return $this->render('YourTemplate.html.twig', array(
        'user_with_books' => $user_with_books,
));

在树枝上:

{% for book in user.books %}
    {{ book.title }}
{% endfor %}

一些注意事项:

  1. 对于多个用户,您必须更改查询(可以延迟加载但不建议)。
  2. 如果是大量数据,你可以通过获得标量结果(数组)来提升性能
  3. 如果您需要对无法合并的用户进行不同的查询,则必须存储不同的变量(对象或数组)。这就是我将它命名为“user_with_books”的原因。但是,如果您只在模板中拥有此用户,则可以将其称为“用户”。
  4. user.getAddressesByUserId(user.getId())< - 将数据从一个模型传递到查询是控制器(或服务)的责任。最佳做法是避免在模板中执行此操作。
  5. 所以答案是: 您无法对自定义存储库方法执行任何操作,因为它是一个函数。自身的功能不代表任何数据。因此,您可以通过该功能检索实际数据 并显示该数据。