Symfony/Doctrine:如何减少select查询的数量?(多层次关联实体;+ jsonSerialize())


Symfony/Doctrine: How to reduce the num of SELECT-queries? (Multi-level associated entities; twig + jsonSerialize())

由于我最后一个问题的答案,我能够减少 SELECT -查询在第一层。不幸的是,关联实体的链接更深,例如:

Item -> Group -> Subscriber -> User -> username

<<p> 库方法/strong>:
// ItemRepository
public function findAll() {
    return $this->createQueryBuilder('item')
                ->addSelect('groups')->join('item.groups', 'groups')
                ->getQuery()->getResult()
}
<<p> 枝模板/strong>:
{% for item in items %}
    {# Level: 0 #}
    Name: {{ item.name }}<br/>
    Groups:<br/>
    <ul>
        {# Level: 1 #}
        {% for group in item.groups %}
           <li>{{ group.name }}<br/>
               <ol>
               {# Level: 2 #}
               {% for subscriber in group.subscribers %}
                   {# Level: 3 #}
                   <li>{{ subscriber.user.username }}</li>
               {% endfor %}
               </ol>
           </li>
        {% endfor %}
    </ul>
{% endfor %}

注意:我使用jsonSerialize来准备JSON-data,其中也包括多级迭代。

use JsonSerializable;
// ...
class Item implements JsonSerializable {
    // ...
    public function jsonSerialize() {
        $subscribers = array();
        $groups      = $this->getGroups();
        foreach ($groups as $group) {
            foreach ($group->getSubscribers() as $subscriber) {
                $subscribers[$subscriber->getId()] = array(
                    'userId'   => $subscriber->getUser()->getId();
                    'username' => $subscriber->getUser()->getUsername();
                );
            }
        }
        return array(
            'id'          => $this->getId(),
            'subscribers' => $subscribers
            // ...
        );
    }
}

是否有一种方法来加入更深的关联数据以及减少 SELECT -查询再次(for twig和jsonSerialize())?

我建议您在特定查询中更改获取模式,如文档中所述。

所以你可以这样描述你的查询:

$qb =  $this->createQueryBuilder('item')
                ->addSelect('groups')->join('item.groups', 'groups'); // Not necessary anymore
        $query = $qb->getQuery();
        // Describe here all the entity and the association name that you want to fetch eager
        $query->setFetchMode("YourBundle''Entity''Item", "groups", ClassMetadata::FETCH_EAGER);
        $query->setFetchMode("YourBundle''Entity''Groups", "subscriber", ClassMetadata::FETCH_EAGER);
        $query->setFetchMode("YourBundle''Entity''Subscriber", "user", ClassMetadata::FETCH_EAGER);
        ...
return $qb->->getResult();

注:

在查询期间更改读取模式只能用于一对一和多对一关系

希望对您有所帮助