2013-07-16 28 views
13

Próbuję utworzyć formularz z danymi w typie kolekcji w zależności od zalogowanego użytkownika. Śledzę this chapter of the Symfony cookbook.Symfony formularz query_buider i repozytorium jednostek

Wszystko działa poprawnie, gdy opcja query_builder jest zamknięciem, w którym otrzymuję moje dane z DQL. Ponieważ dane muszą być pobierane z różnych lokalizacji w kodzie, wolałbym zdefiniować zapytanie w klasie Repository.

Oto funkcja w moim repozytorium:

public function findOwnedBy($user) { 
    $query = $this->getEntityManager()->createQuery("SELECT l FROM MyBundle:Article a JOIN a.owndBy u WHERE u.id = :userId"); 
    $query->setParameters(array("userId"=>$user->getId())); 
    return $query->getResult(); 
} 

Funkcja ta działa, gdy nazywa się kontrolera i zwraca tablicę art. Oto urywek doc symfony:

$formOptions = array(
        'class' => 'Acme\DemoBundle\Entity\User', 
        'multiple' => false, 
        'expanded' => false, 
        'property' => 'fullName', 
        'query_builder' => function(EntityRepository $er) use ($user) { 
         // build a custom query, or call a method on your repository (even better!) 
        }, 
       ); 

Kiedy kładę wezwanie do mojego repozytorium funkcji w query_builder, pojawia się błąd: Expected argument of type "Doctrine\ORM\QueryBuilder", "array" given, co mogę zrozumieć, bo moim repozytorium zwraca tablicę jednostki, nie QueryBuilder.

Nie chcę duplikować kodu i utworzyć nowego QueryBuilder w formularzu. Jaka jest najlepsza praktyka korzystania z zapytania z repozytorium? Myślałem o posiadaniu dwóch funkcji w repozytorium, jeden zwracający tablicę, a drugi zwracający QueryBuilder, ale komentarz w dokumencie Symfony "lub wywołanie metody na twoim repozytorium (jeszcze lepiej!)" Niech pomyślę, że jest lepszy sposób w tym przypadku.

Odpowiedz

24

To powinno być łatwe. Wykonaj następujące czynności:

public function queryOwnedBy($user) { 

    $query = $this->createQueryBuilder('a') 
      ->from('MyBundle:Article', 'a') 
      ->innerJoin('a.owndBy', 'u') 
      ->where('u.id = :id')     
      ->setParameter('id', $user->getId()); 

    return $query; 
} 

public function findOwnedBy($user) { 
    return $this->queryOwnedBy($user) 
      ->getQuery() 
      ->getResult(); 
} 

Następnie w budowniczy forma:

$formOptions = array(
    'class' => 'Acme\DemoBundle\Entity\User', 
    'multiple' => false, 
    'expanded' => false, 
    'property' => 'fullName', 
    'query_builder' => function(EntityRepository $er) use ($user) { 
     return $er->queryOwnedBy($user); 
    }, 
); 

EDIT

Dziękuję za ncatnow i Unagi Zmieniłem dotychczasowe funkcje do zwrotu QueryBuilder

+0

Ja również powinienem być łatwy i to była moja pierwsza próba. To zwróci mi błąd 'Oczekiwany argument typu" Doctrine \ ORM \ QueryBuilder "," array "given'. Wydaje się, że 'query_builder' oczekuje na obiekt QueryBuilder, niezależnie od tego, czy jest on podany bezpośrednio, czy zwrócony przez zamknięcie. – Florent

+0

Edytowano wpis. Utwórz dwie funkcje, na której zwraca zapytanie, a drugą zwraca wynik. W konstruktorze formularzy wywołaj funkcję, która zwraca zapytanie. To powinno zadziałać i nadal jest DRY. Przepraszam, zmienię nazwy, ponieważ nie są odpowiednie. – saamorim

+0

hehe, to jest rzeczywiście to, co zrobiłem i co opisałem w ostatnim akapicie pytania. Pójdę w ten sposób, mały komentarz w dokumencie Symfony pozwala sądzić, że może działać po wyjęciu z pudełka, jest mylący;) – Florent

8

Właśnie zrobiłem małą poprawkę odpowiedzi saamorim. Kod roboczy byłby taki:

+0

Dziękuję. Zintegrowałem twoją odpowiedź w moim poście i zmieniłem zapytanie zgodnie z przykładem. – saamorim