2015-03-14 3 views
0

Я пытаюсь получить связанные объекты через 3 таблицы (пользователь, клиент, учетная запись). Пользователь имеет отношение «один ко многим» к клиенту, клиент имеет отношение «один ко многим» к учетной записи. Я легко извлечь все клиенты для одного конкретного пользователя, используя этот простой код:Doctrine, получающий косвенно связанные объекты

$user = $this->getUser(); 
$id = $user->getId(); 
$user = $this->getDoctrine()->getRepository('AcmeUserBundle:User')->find($id); 
$clients = $user->getClients(); 

Кроме того, у меня нет проблемы с извлечением всех учетных записей для одного конкретного клиента, используя этот код:

$client = $this->getDoctrine()->getRepository('AcmeUserBundle:Client')->find($clientref); 
$accounts = $client->getAccounts(); 

Теперь я хочу получать непосредственно все учетные записи, относящиеся к одному пользователю. Как мне это сделать? Я попытался следующие:

$user = $this->getUser(); 
$id = $user->getId(); 
$user = $this->getDoctrine()->getRepository('AcmeUserBundle:User')->find($id); 
$client = $user->getClients(); 
$accounts = $client->getAccounts(); 

Но я получаю следующее сообщение об ошибке «Попытка вызвать метод„getAccounts“на классе„Учение \ ORM \ PersistentCollection“». Я считаю, что чего-то не хватает, потому что «Учетные записи» не могут быть ленивы загружены доктриной, когда я получаю пользователя, только «Клиенты». Каков наилучший способ достичь этого? Не могли бы вы привести пример кода, который будет работать (например, итерация или запрос DQL)? Спасибо.

+0

Подсказка: $ clients = $ user-> getClients(); потому что getClients вернет массив. – Cerad

ответ

0

Это Поведение. Коллекция возвращается $user->getClients(), а не один объект. Коллекции Doctrine не проксируют вызовы методов своим членам. Существует два способа решить вашу проблему:

Простой. Положитесь на ленивую нагрузку Доктрины. Допустим, вы используете данные, как это:

foreach ($client as $user->getClients()) { 
    foreach ($account as $client->getAccounts()) { 
     echo $account->getId(); 
    } 
} 

ORM будет получать счета автоматически, работает отдельный запрос к базе данных для каждого клиента. Это будет сделано только в том случае, если вы не заботитесь о производительности: O (N) запросы плохие.

Лучшее. Используйте LEFT JOIN, чтобы получить все данные с одним запросом в базу данных.

$qb = $this->getDoctrine()->getManager()->createQueryBuilder() 
    ->select('u, c, a') 
    ->from('AcmeUserBundle:User', 'u') 
    ->leftJoin('u.clients', 'c') 
    ->leftJoin('c.accounts', 'a') 
    ->where('u.id = :id'); 

$user = $qb->getQuery() 
    ->setParameter('id', $id) 
    ->getOneOrNullResult(); 
Смежные вопросы