Symfony将整个对象从数据库中获取并传递给Twig吗?

3
我正在尝试优化我的Symfony项目,想知道当我从控制器将实体对象传递到Twig模板时,是否会从数据库中完全获取(所有字段)该对象,还是仅获取在模板中使用的字段?
假设我有一个书籍实体,它具有标题和摘要字段。在控制器中,我从相应的存储库中获取所有书籍:
$books = $booksRepository->findAll();

然后将其传递给Twig模板:

return $this->render('books.html.twig', [
    'books' => $books
]);

接下来,在books.html.twig中,我仅使用title字段遍历books对象:

{% for book in books %}
    Title: {{ book.title }}<br>
{% endfor %}

我想知道Symfony是否也从数据库中读取abstract字段。当然,这只是一个例子,生产项目可能有更多字段的实体。因此,我认为在某些网页上获取未使用的字段可能会给应用程序和数据库带来额外的负载。如果我的初始问题的答案是肯定的,我还想知道用于避免获取未使用字段的技术。
我尝试调试Symfony和Doctrine类,但最终在使用的类数量中迷失了方向,找不到答案。

简而言之,除非你已经指定了“SELECT”列,否则会从数据库检索所有字段。真正的问题是为什么你认为这可能是一个问题。 - Phil
1
这是Doctrine做的事情。阅读Doctrine文档是值得的。Doctrine支持所谓的“partials”,其中您可以指定要获取哪些列,但它们可能会很棘手,因为实体没有完全填充,如果尝试访问未初始化的列,则可能会发生有趣的事情。否则,是的,所有映射的列都将被获取。但再次阅读一些文档。它们包含关于幕后发生的事情的部分。 - Cerad
1
一旦您执行 $books = $booksRepository->findAll();,Doctrine 就会从数据库中调用所有书籍的数据,并将其全部填充。如果您的数据库中有很多书籍,则 PHP/Doctrine 将使用大量内存。如果要避免这种情况:不要加载所有书籍(切割和分片),或者如果您需要在响应中使用它们所有,可以像 @Cerad 建议的那样使用部分。无论如何,在 Twig 渲染之前,您都可以使用专用缓存层来存储标题数组,而不是提供所有填充的书籍。存储标题并避免调用 findAll() 方法。 - Alexandre Tranchant
谢谢,您的回答澄清了许多方面! - Fuad
1个回答

0

这种行为与Symfony或Twig无关。 它与Doctrine 2以及您在Repositories中编写代码的方式有关。

当使用$books = $booksRepository->findAll();时,它将始终获取所有字段。 所有本地Doctrine函数都是如此。

find()
findOneBy()
findAll()
findBy()

如果您只想获取字段的子集,您将需要创建自定义存储库函数。例如:
$query = $this->createQueryBuilder('book')->select('book.id, book.title, book.author');

并且调用它而不是您的findAll()。

但就个人而言,我并不完全同意

我认为在某些网页上获取未使用的字段可能会导致额外的负载

您必须考虑以毫秒为单位的绝对收益价值。大多数情况下,对于“小”实体,仅查询字段子集将使您的查询获得0.000xxx毫秒的收益。 因此,我建议您不要自动创建自定义存储库方法,因为负载/时间收益通常是无关紧要的,并且只有在出现性能问题时才执行此操作。这将防止您创建许多需要在未来维护的代码。 不要固执于一种信仰哈哈


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