2013-03-21 2 views
1

Я не понимаю, как заставить его работать.Как работает createQueryBuilder и leftJoin?

у меня есть:

  • стол partner с полями id и name
  • стол partner_address с двумя полями: id_partner и id_address
  • столиком address с полями id и внешним ключом id_town который ссылается town(id)
  • стол town с fie LDS id, name и postal_code

Я хочу, чтобы выбрать всех партнеров, которые находятся в городах с конкретной postal_code Этот запрос работает:

SELECT p.nom, v.nom 
FROM partner p 
JOIN partner_address pa 
ON pa.id_partner=p.id 
JOIN address a 
ON pa.id_address = a.id 
JOIN town t 
ON a.id_town=t.id 
WHERE t.postal_code='13480'; 

Теперь я хочу, чтобы «перевести» его в доктрине 2 полный синтаксис, следующий the documentation.

Так что я сделал пользовательский репозиторий:

src/Society/Bundle/MyProjectBundle/Repository/PartnerRepository.php

В этом хранилище, я пытаюсь создать соответствующую функцию:

<?php 

namespace HQF\Bundle\PizzasBundle\Repository; 

use Doctrine\ORM\EntityRepository; 

class PartenaireRepository extends EntityRepository 
{ 
    /** 
    * Get all active partners from a given postal code. 
    */ 
    public function findAllActiveByCp($cp) 
    { 
     return $this->createQueryBuilder('p') 
      ->where('p.dateVFin IS NULL') 
      ->andWhere('p.cp=:cp') 
      ->addOrderBy('p.cp', 'DESC') 
      ->setParameter('cp', $cp); 
    } 
} 

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

Я пытаюсь что-то вроде этого, но он не работает:

public function findAllActiveByCp($cp) 
{ 
    $qb = $this->createQueryBuilder('p'); 
    return $qb 
     ->leftJoin('partner_address pa ON pa.id_partner=p.id') 
     ->leftJoin('address a ON pa.id_address = a.id') 
     ->leftJoin('town t ON a.id_ville=t.id') 
     ->where('p.dateVFin IS NULL') 
     ->andWhere('t.cp=:cp') 
     ->addOrderBy('t.cp', 'DESC') 
     ->setParameter('cp', $cp); 
} 

Я получаю эту ошибку:

Warning: Missing argument 2 for Doctrine\ORM\QueryBuilder::leftJoin(), called in /blabla/Repository/PartenaireRepository.php on line 18 and defined in /blabla/symfony/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php line 767

ответ

6

Вы должны присоединиться только свойством, что выбранный объекта есть.

В первом параметре join() или leftJoin() или xxxJoin() вы передаете имя атрибута, относящегося к выбранному объекту, а во втором - псевдоним для объединенного объекта.

Попробуйте simmilar к этому:

$q = $this->em()->createQueryBuilder(); 

$q->select(['item', 'itemContact']) 
    ->from('ModuleAdmin\Entity\CustomerEntity', 'item') 
    ->leftJoin('item.contacts', 'itemContact') 
    ->andWhere($q->expr()->like('item.name', ':customerNameStart')); 

Конечно, CustomerEntity содержит OneToMany соотношение в поле contacts.

Помните, что в операторе отбора вы должны выбрать корневой объект (в моем примере CustomerEntity с псевдонимом item).


Редактировать Оливье Pons, чтобы добавить, как я узнал, что решение, и пометить этот ответ действительным, потому что он поставил меня на правильный путь, спасибо Адам!

В файле PartenaireRepository.php Я правильно использовал createQueryBuilder('p'). Вот как сделать два присоединяется подряд, используя createQueryBuilder():

class PartenaireRepository extends EntityRepository 
{ 

    /** 
    * Récupération de tous les partenaires donnés pour un 
    * code postal donné. 
    */ 
    public function findAllActiveByCp($cp) 
    { 
     return $this->createQueryBuilder('p') 
      ->leftJoin('p.adresses', 'a') 
      ->leftJoin('a.ville', 'v') 
      ->where('v.cp=:cp') 
      ->setParameter('cp', $cp); 
    ... blabla 
    } 
} 
+0

У меня все еще есть эта проблема с« ManyToOne ». Один элемент может иметь один или несколько контактов. Поэтому, с моей точки зрения, это должен быть OneToMany, а не ManyToOne. Я прав. А если нет, есть ли у вас «простой способ» избежать этого недоразумения? –

+0

Да, у вас есть право. У меня есть «опечатка» в моем ответе, только что отредактированная :). Конечно, в моем коде есть «OneToMany». Тем не менее, надеюсь, что я помог. Помните, что вы обязаны выбрать корневой объект. – Athlan

+0

Вы правы! Я нахожусь на правильном пути: в моем 'PartenaireRepository.php' это работает:' $ this-> createQueryBuilder ('p') -> leftJoin ('p.adresses', 'a'); ', но теперь, если я хочу ** другой ** присоединиться к адресам, как я могу это сделать? –

0

Я считаю, что для того, что вы делаете, вы должны предоставить четыре аргумента методу leftJoin.

->leftJoin('partner_address', 'pa', 'ON', 'pa.id_partner = p.id') 

Таким образом, ваш запрос строитель цепь должна выглядеть следующим образом

public function findAllActiveByCp($cp) 
{ 
    $qb = $this->createQueryBuilder('p'); 
    return $qb 
     ->leftJoin('partner_address', 'pa', 'ON', 'pa.id_partner = p.id') 
     ->leftJoin('address', 'a', 'ON', 'pa.id_address = a.id') 
     ->leftJoin('town', 't', 'ON', 'a.id_ville = t.id') 
     ->where('p.dateVFin IS NULL') 
     ->andWhere('t.cp=:cp') 
     ->addOrderBy('t.cp', 'DESC') 
     ->setParameter('cp', $cp) 
    ; 
} 
+0

Я пытался, но есть ошибка на '-> LeftJoin ('partner_address')': '[Семантическая Error] строка 0, столбец 68 near 'partner_address': Ошибка: Class 'partner_address' не определен. '. Я этого не понимаю. Почему это должен быть «класс»? Это должна быть таблица базы данных, конец истории! –

+0

А у вас есть класс сущности Doctrine для каждой таблицы? т. е. существует ли 'HQF \ Bundle \ PizzasBundle \ Entity \ PartnerAddress', который будет отображаться в таблице' partner_address'? Если это так, замените 'partner_address' на' PartnerAddress'. –

+0

и да, я согласен, это должен быть стол, а не класс, но я думаю, именно поэтому он называется ORM. Если вы предпочитаете использовать QueryBuilder, но с таблицами напрямую, в DBAL есть один доступный, но не имеет всех функций, таких как ORM. –

Смежные вопросы