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

时间:2015-07-29 17:54:52

标签: php symfony orm doctrine-orm twig

由于my last question的回答,我能够在第一级减少 SELECT - 查询。不幸的是,相关的实体更深层次地联系在一起,例如:

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

存储库方法

// ItemRepository
public function findAll() {
    return $this->createQueryBuilder('item')
                ->addSelect('groups')->join('item.groups', 'groups')
                ->getQuery()->getResult()
}

树枝模板

{% 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数据,其中包括多级迭代。

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 - 查询次数 (对于twig和jsonSerialize())

1 个答案:

答案 0 :(得分:3)

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

因此,您可以按如下方式描述您的查询:

$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();

NB:

  

在查询期间更改提取模式只能是一对一的   和多对一的关系。

希望这个帮助