Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Symfony][Symfony2] czy mogę w klasie Entity reprezentującej tabele wykonać zapytanie?
Forum PHP.pl > Forum > PHP > Frameworki
wiewiorek
Mam klasę KategorieEntity i ZdjeciaEntity. W widoku w pętli wyświetlam wszystkie kategorie, jednak chciałbym wywołać moją metodę pobierzNazweMiniaturyKategorii() z KategorieEntity na obiekcie reprezentującym pojedynczą kategorię, tzn. w widoku mam:

  1. <?php foreach ($kategorie as $kategoria): ?>
  2. <?php echo $kategoria->getNazwa() ?>
  3. <img src="<?php echo $view['assets']->getUrl('uploads/'.$kategoria->pobierzNazweMiniaturyKategorii($kategoria->getId())) ?>" />
  4. <?php endforeach; ?>


W klasie KategorieEntity:
  1. class KategorieEntity
  2. {
  3. protected $id;
  4.  
  5. protected $nazwa;
  6.  
  7. //moja metoda:
  8. public function pobierzNazweMiniaturyKategorii($idKategorii)
  9. {
  10. $zdjecie = $this->getEntityManager()
  11. ->createQuery('SELECT z FROM AcmeStronaBundle:ZdjeciaEntity z
  12. JOIN z.kategoria k
  13. WHERE k.id = :idKategorii AND z.glowneKategorii = true')
  14. ->setParameter('idKategorii', $idKategorii)
  15. ->getSingleResult();
  16.  
  17. return $zdjecie->getNazwaMiniatury();
  18. }
  19.  
  20.  
  21. ................
  22. }


Niestety wykonanie zapytania w klasie Entity i wywołanie metody z tej klasy w widoku chyba nie jest mozliwe, bo to nie działa (nie jest też wyświetlany komunikat błedu), więc jak to zrobić?
pedro84
Entity Repository. Czytaj tu lub tu i jeszcze tu.
wiewiorek
Z repozytorium też już próbowałem, tzn. przeniosłem tę metodę do klasy:

  1. class KategorieRepository extends EntityRepository
  2. {
  3. public function pobierzNazweMiniaturyKategorii($idKategorii)
  4. {
  5. $zdjecie = $this->getEntityManager()
  6. ->createQuery('SELECT z FROM AcmeStronaBundle:ZdjeciaEntity z
  7. JOIN z.kategoria k
  8. WHERE k.id = :idKategorii AND z.glowneKategorii = true')
  9. ->setParameter('idKategorii', $idKategorii)
  10. ->getSingleResult();
  11.  
  12. return $zdjecie->getNazwaMiniatury();
  13. }
  14.  
  15.  
  16. }



i wciąż wywołanie jej w widoku nie działa.
pedro84
Logi co mówią?
wiewiorek
No nic istotnego własnie nie mówią:

[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest". [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\RouterListener::onEarlyKernelRequest". [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\SessionListener::onKernelRequest". [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\Security\Http\Firewall::onKernelRequest". [] []
[2012-03-21 14:53:44] security.DEBUG: Read SecurityContext from the session [] []
[2012-03-21 14:53:44] security.DEBUG: Reloading user from user provider. [] []
[2012-03-21 14:53:44] doctrine.DEBUG: SET NAMES UTF8 ([]) [] []
[2012-03-21 14:53:44] doctrine.DEBUG: SELECT t0.user_id AS user_id1, t0.username AS username2, t0.email AS email3, t0.password AS password4, t0.salt AS salt5 FROM user t0 WHERE t0.user_id = ? ([1]) [] []
[2012-03-21 14:53:44] security.DEBUG: Username "admin" was reloaded from user provider. [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\RouterListener::onKernelRequest". [] []
[2012-03-21 14:53:44] request.INFO: Matched route "kategorie_zarzadzanie" (parameters: "_controller": "Acme\StronaBundle\Controller\KategorieController::indexAction", "_route": "kategorie_zarzadzanie") [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\AsseticBundle\EventListener\RequestListener::onKernelRequest". [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.controller" to listener "Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector::onKernelController". [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\ControllerListener::onKernelController". [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\ParamConverterListener::onKernelController". [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener::onKernelController". [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.controller" to listener "Acme\DemoBundle\ControllerListener::onKernelController". [] []
[2012-03-21 14:53:44] event.DEBUG: Notified event "kernel.controller" to listener "JMS\SecurityExtraBundle\Controller\ControllerListener::onCoreController". [] []
[2012-03-21 14:53:44] doctrine.DEBUG: SELECT k0_.id AS id0, k0_.nazwa AS nazwa1, k0_.opis AS opis2, k0_.data_dodania AS data_dodania3, k0_.data_modyfikacji AS data_modyfikacji4 FROM kategorie k0_ ORDER BY k0_.data_dodania DESC ([]) [] []
destroyerr
Niby nic istotnego nie mówią, ale jednak brakuje w nich Twojego zapytania. Zastanów się czemu jego tam nie ma.

Wykonywanie zapytań z poziomu encji moim zdaniem jest nie poprawne. Powinieneś albo to zrobić tak jak wspomniał pedro84, albo w kategorii przejść po wszystkich zdjęciach i wybrać odpowiednie.
wiewiorek
Zrobiłem w końcu w ten sposób, że w akcji kontrolera wywołuję tę metodę z repozytorium i zapisuje dane do tablicy, a potem przekazuję ją do widoku i z niej korzystam:

  1. class KategorieController extends Controller
  2. {
  3.  
  4. public function indexAction()
  5. {
  6. $em = $this->getDoctrine()->getEntityManager();
  7.  
  8. $kategorie = $em->createQuery('SELECT k FROM AcmeStronaBundle:KategorieEntity k ORDER BY k.dataDodania DESC')->getResult();
  9.  
  10. $zdjeciaKategorii = array();
  11. foreach($kategorie as $kategoria)
  12. {
  13. $zdjeciaKategorii[$kategoria->getId()] = $this->getDoctrine()
  14. ->getRepository('AcmeStronaBundle:KategorieEntity')
  15. ->pobierzNazweMiniaturyKategorii($kategoria->getId());
  16. }
  17.  
  18. ...................
  19. }
  20.  
  21. ............
  22. }
  23.  


A w widoku:
  1. <?php foreach ($kategorie as $kategoria): ?>
  2. <?php echo $kategoria->getNazwa() ?>
  3. <img src="<?php echo $view['assets']->getUrl('uploads/'.$zdjeciaKategorii[$kategoria->getId()]) ?>" />
  4. <?php endforeach; ?>


To jest chyba jednak najlepsze rozwiązanie, wadą rozwiązania jest to że zarówno w akcji kontrolera jak i w widoku mam tę samą praktycznie pętle, ale co tam. smile.gif
destroyerr
Cytat
To jest chyba jednak najlepsze rozwiązanie

To jest akurat jedno z najgorszych rozwiązań: zapytanie w kontrolerze w dodatku w pętli i do tego jeszcze polskie nazewnictwo wymieszane z angielskim.
wiewiorek
Cytat(destroyerr @ 21.03.2012, 20:40:08 ) *
To jest akurat jedno z najgorszych rozwiązań: zapytanie w kontrolerze w dodatku w pętli i do tego jeszcze polskie nazewnictwo wymieszane z angielskim.


Akurat jedyne działające, podobnie jak to - update z joinem w DQL, nie mam dostępu do id_kategorii w ZdjeciaEntity więc żeby zrobić update muszę użyć joina, ale co fajniejsze to zapytanie nie działa (nikt na google groups doctrine nie wiedział i na forum symfony również co jest nie tak):
  1. $this->getEntityManager()
  2. ->createQuery('UPDATE AcmeStronaBundle:ZdjeciaEntity z
  3. JOIN z.kategoria k
  4. SET z.glowneZdjecie = false
  5. WHERE k.id = :idKategorii')
  6. ->setParameter('idKategorii', 5)
  7. ->execute();


Rozwiązałem więc to tak - zrobić najpierw selecta, a potem update:
  1. $zdjeciaGlowneKategorii = $this->getEntityManager()
  2. ->createQuery('SELECT z FROM AcmeStronaBundle:ZdjeciaEntity z
  3. JOIN z.kategoria k
  4. WHERE k.id = :idKategorii AND z.glowneKategorii = true')
  5. ->setParameter('idKategorii', $idKategorii)
  6. ->getResult();
  7.  
  8. foreach($zdjeciaGlowneKategorii as $zdjecieGlowneKategorii)
  9. {
  10. $this->getEntityManager()
  11. ->createQuery('UPDATE AcmeStronaBundle:ZdjeciaEntity z SET z.glowneKategorii = false')
  12. ->execute();
  13. }
  14.  


Ah jakie to Symfony 2 jest cudowne, tyle rzeczy trzeba robić naookoło. tongue.gif

A co do mieszania polskiego z angielskim, zawsze tak robię jak uczę się nowych technologii, robię to od momentu jak kiedyś uczyłem się WinAPI - wówczas pisałem wszystko po angielsku, a jak wróciłem do kodu po miesiącu to nie wiedziałem już co jest mego autorstwa a co było częścią WinAPI. Może to i głupie oraz nieeleganckie, ale potem przynajmniej wiem i nie muszę szukać czy daną metodę napisałem ja czy jest częścią danej technologii. Takie postępowanie wielokrotnie zaoszczędziło mi sporo czasu. Gdy tylko dochodzę do wniosku, że znam już w miarę dobrze daną technologię to przestawiam się na angielski.
kudlatypawelek
Zapytania powinno pisać się w klasach Repository. Jeżeli mamy własne xxxRepository trzeba je dodac w klasie encji w sekcji "use". Komunikację z EntityManagerem oraz złożone operacje najlepiej robić w serwisach i z nich przekazywać gotowe wyniki do kontrolerów. W kontrolerach zaś tylko wołać widoki / robić forwardy lub redirecty, ewentualne odpalać jakieś inne akcje, najlepiej niedotyczące modelu; tu może być problem bo często jednak w kontrolerach operujemy na formularzach i robimy persist/flush co nie do końca jest okey.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.