Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [SF][SF2]DI w konrolerze
Matrix12
post
Post #1





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 22.03.2015

Ostrzeżenie: (0%)
-----


Witam,


mam pytanie. Posiadam kilka kontrolerów, są to czyste CRUD'y i stworzyłem dodatkowy kontroler który będzie nimi wszystkimi zarządzał.
Próbuje wrzucić w konstruktorze np.


  1. public function __construct(NewsController $news)
  2. {
  3. $this->news = $news;
  4.  
  5. }
  6.  


Niestety wyświetla mi cały czas, że $news powinna być instancją klasy NewsController( wiem że tak powinno być ) ale dlaczego automatycznie nie jest to ładowane? Czy jakiś serwis muszę do tego napisać? Jak wygląda przykładowa implementacja takiego rozwiązania ?
Go to the top of the page
+Quote Post
kpt_lucek
post
Post #2





Grupa: Zarejestrowani
Postów: 428
Pomógł: 77
Dołączył: 10.07.2011
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Bo musisz zdefiniować DI poprzez konfigurację bundle'a.

  1. services:
  2. base_controller:
  3. class: My\Bundle\Controller\BaseController
  4. arguments: [ @xyz, @abc ]
  5. controler_1:
  6. class: My\Bundle\Controller\Controller1
  7. arguments: [ @base_controller ]
  8. #itd
  9. #gdzie @xyz jest definicją serwisu (usługi) i tylko w ten sposób możesz się do niego odwoływać aby DI działało poprawnie


Ten post edytował kpt_lucek 11.04.2015, 12:50:28
Go to the top of the page
+Quote Post
Matrix12
post
Post #3





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 22.03.2015

Ostrzeżenie: (0%)
-----


Czyli rozumiem, że jest to np. tak:
  1. services:
  2. news_controller:
  3. class: My\Bundle\Controller\NewsController
  4. admin_controler:
  5. class: My\Bundle\Controller\AdminController
  6. arguments: [ @base_controller ]


gdzie potem odwołuje się do tego tak :


  1.  
  2. <?php
  3.  
  4.  
  5. class AdminController extends Controller
  6. {
  7.  
  8. public function__construct(NewsController $news)
  9. {
  10. $this->news = $news;
  11. }
  12.  


Ten post edytował Matrix12 11.04.2015, 12:55:28
Go to the top of the page
+Quote Post
kpt_lucek
post
Post #4





Grupa: Zarejestrowani
Postów: 428
Pomógł: 77
Dołączył: 10.07.2011
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Zacznijmy może od tego co chcesz zrobić, bo w praktyce nie wiem jak Ci pomóc/wytłumaczyć/naprowadzić na to co mógłbyś zrobić.
Go to the top of the page
+Quote Post
Matrix12
post
Post #5





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 22.03.2015

Ostrzeżenie: (0%)
-----


Mam kilka crudów którymi chciałbym zarządzać z AdminController... dlatego chce nauczyć wstrzykiwać zależności bo wtedy będę mógł się odwołać do każdego z tych crudów.
Go to the top of the page
+Quote Post
kpt_lucek
post
Post #6





Grupa: Zarejestrowani
Postów: 428
Pomógł: 77
Dołączył: 10.07.2011
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Zacznijmy od tego że Twój controller rozszerza BaseController.

Miej na uwadze iż BaseController zawiera swój constructor, a w nim są wstrzykiwane zależności chociażby do container'a.

Jeżeli chcesz, aby Twój AdminController zbierał wszystkie pozostałe, możesz do tego użyć serwisów tagowanych + compiler pass, dzięki temu nie musisz wstrzykiwać każdego z osobna (IMG:style_emoticons/default/smile.gif)

Zainteresuj się Tym, tym i tym.
Go to the top of the page
+Quote Post
Matrix12
post
Post #7





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 22.03.2015

Ostrzeżenie: (0%)
-----


Próbowałem zdefiniować kontroler jako serwis ale to nie działa;/
Go to the top of the page
+Quote Post
kpt_lucek
post
Post #8





Grupa: Zarejestrowani
Postów: 428
Pomógł: 77
Dołączył: 10.07.2011
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Stwierdzenie "nie działa" mówi tyle co nic. Napisz konkrety proszę.

Co zrobiłeś, w jaki sposób, jak wygląda Twój controller (1.,2.,3.,n.), jaki błąd dostajesz i jak się do tego odwołujesz

Ten post edytował kpt_lucek 11.04.2015, 13:25:41
Go to the top of the page
+Quote Post
Matrix12
post
Post #9





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 22.03.2015

Ostrzeżenie: (0%)
-----


Dostaje taki bład:


  1.  
  2. There is no extension able to load the configuration for "news_controller" (in \src\Acme\AdminBundle\DependencyInjection/../Resources/config\services.yml). Looked for namespace "news_controller", found none




services.yml wygląda tak :

  1. news_controller:
  2. class: Acme\NewsBundle\Controller\NewsController
  3.  
  4. admin_controller:
  5. class: Acme\AdminBundle\Controller\AdminController
  6. arguments : [@news_controller]




kontroler wygląda tak:
  1.  
  2. <?php
  3.  
  4. namespace Acme\AdminBundle\Controller;
  5.  
  6.  
  7. use Symfony\Component\HttpFoundation\Request;
  8. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  9. use Symfony\Component\HttpFoundation\Response;
  10.  
  11. use Acme\NewsBundle\Controller\NewsController;
  12. /**
  13. *
  14. */
  15. class AdminController extends Controller
  16. {
  17. public $news;
  18. function __construct(NewsController $news)
  19. {
  20. $this->news = $news;
  21. }
  22.  
  23.  
  24. }


Ten post edytował Matrix12 11.04.2015, 13:39:21
Go to the top of the page
+Quote Post
kpt_lucek
post
Post #10





Grupa: Zarejestrowani
Postów: 428
Pomógł: 77
Dołączył: 10.07.2011
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


  1. services:
  2. news_controller:
  3. class: Acme\NewsBundle\Controller\NewsController
  4.  
  5. admin_controller:
  6. class: Acme\ExampleBundle\Controller\AdminController
  7. arguments : [@news_controller]

To po pierwsze,

  1. <?php
  2.  
  3. namespace Acme\AdminBundle\Controller;
  4.  
  5.  
  6. use Symfony\Component\HttpFoundation\Request;
  7. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  8. use Symfony\Component\HttpFoundation\Response;
  9.  
  10. use Acme\NewsBundle\Controller\NewsController;
  11. /**
  12. *
  13. */
  14. class AdminController extends Controller
  15. {
  16. public $news;
  17. function __construct(NewsController $news)
  18. {
  19. // pamiętaj co pisałem o constructorze w controllerach extendujących BaseController
  20. $this->news = $news;
  21. }
  22.  
  23.  
  24. }


Pamiętaj o jeszcze jednej rzeczy,

Rejestrując controller jako usługę (serwis), nie powinieneś (o ile pamiętam, to nie możesz) extendować Symfony\Bundle\FrameworkBundle\Controller\Controller, więc Wszystkie zależności dołączasz poprzez DI (wystrzegaj się wstrzykiwania całego container'a).
Go to the top of the page
+Quote Post
Forti
post
Post #11





Grupa: Zarejestrowani
Postów: 655
Pomógł: 73
Dołączył: 2.05.2014

Ostrzeżenie: (0%)
-----


Tworzenie DI dla controller to imo zla praktyka. Zrób sobie coś takiego:

  1. services:
  2. acme.controller_service:
  3. class: Acme\ExampleBundle\Service\ControllerService
  4. arguments: ['@service_container']


  1. <?php
  2.  
  3. namespace Acme\ExampleBundle\Service;
  4.  
  5. use Symfony\Component\DependencyInjection\ContainerInterface as Container;
  6.  
  7. class ControllerService
  8. {
  9. protected $container;
  10.  
  11. public function __construct(Container $container)
  12. {
  13. $this->container = $container;
  14. }
  15. }


i teraz normalnie w controller robisz np.
  1. $this->get('service_jakis_sobie')


. Tutaj robisz
  1. $this->container->get('service_jakis_sobie')


Trzymasz cała logike w takich "serwisach" (IMG:style_emoticons/default/wink.gif)
Np. do doctrine robisz $this->container->get('doctrine')->getManager. W controllerze w którym "Zarządzasz" robisz:

  1. $this->get('acme.controller_service')



Nie jest to do końca prawidłowe. Powinno unikać się wstrzykiwania całego kontenera usług, a jedynie to co potrzebujemy.


Troche chaotycznie napisałem ponieważ jestem na uczelni. Jak coś to pytaj.

Ten post edytował Forti 11.04.2015, 14:13:07
Go to the top of the page
+Quote Post
kpt_lucek
post
Post #12





Grupa: Zarejestrowani
Postów: 428
Pomógł: 77
Dołączył: 10.07.2011
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Moim zdaniem, tworzenie controllerów jako usług ma swoje plusy i minusy. Do minusów możesz zaliczyć brak dostępu do każdego zarejestrowanego serwisu (usługi), bo nie ładujesz tam container'a. Plusem jest jasne sprecyzowanie zależności controllera, szybka weryfikacja poziomu złożoności logiki tam będącej, łatwiejsze testowanie jak i budowanie go pod konkretną funkcjonalność, dalej idąc tym tropem - przyspieszasz działanie, bo nie ładujesz mega wielkiego container'a do zależności, przez co sam obiekt jest lżejszy.
Go to the top of the page
+Quote Post
Matrix12
post
Post #13





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 22.03.2015

Ostrzeżenie: (0%)
-----


Jednak zdecydowałem tak jak radziłeś :
  1. <?php
  2.  
  3. namespace Acme\AdminBundle\Controller;
  4.  
  5.  
  6. use Symfony\Component\HttpFoundation\Request;
  7. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  8. use Symfony\Component\HttpFoundation\Response;
  9. use Symfony\Component\DependencyInjection\ContainerInterface as Container;
  10.  
  11.  
  12. /**
  13. *
  14. */
  15. class AdminController extends Controller
  16. {
  17. public $container;
  18.  
  19. public function __construct(Container $container)
  20. {
  21. $this->container = $container;
  22. }
  23.  
  24. }




a service.yml wygląda tak :


  1. services:
  2.  
  3.  
  4. acme.admin_controller:
  5. class: Acme\AdminBundle\Controller\AdminController
  6. arguments: ['@admin_controller']



natomiast wyświetla mi taki błąd :

  1. ServiceNotFoundException in CheckExceptionOnInvalidReferenceBehaviorPass.php line 58: The service "acme.admin_controller" has a dependency on a non-existent service "admin_controller".
Go to the top of the page
+Quote Post
kpt_lucek
post
Post #14





Grupa: Zarejestrowani
Postów: 428
Pomógł: 77
Dołączył: 10.07.2011
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Cytat(Matrix12 @ 11.04.2015, 19:29:59 ) *
Jednak zdecydowałem tak jak radziłeś :
  1. <?php
  2.  
  3. namespace Acme\AdminBundle\Controller;
  4.  
  5.  
  6. use Symfony\Component\HttpFoundation\Request;
  7. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  8. use Symfony\Component\HttpFoundation\Response;
  9. use Symfony\Component\DependencyInjection\ContainerInterface as Container;
  10.  
  11.  
  12. /**
  13. *
  14. */
  15. class AdminController extends Controller
  16. {
  17. public $container;
  18.  
  19. public function __construct(Container $container)
  20. {
  21. $this->container = $container;
  22. }
  23.  
  24. }


1. Robisz to błędnie, bo "class AdminController extends Controller" już Ci daje dostęp do container'a ($this->container->get(), lub aliasem $this->get()), tak więc tą kwestię możesz pominąć.
2. W jakim celu "AdminController" musi zawierać pozostałę CRUD'y (controllery)? Nie łatwiej utworzyć usługi (nie controllery, dedykowane serwisy zajmujące się konkretną funkcjonalnością), zarejestrowanie ich i używanie wedle potrzeb w innych usługach / controllerach?
Go to the top of the page
+Quote Post
Matrix12
post
Post #15





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 22.03.2015

Ostrzeżenie: (0%)
-----


Poprzez AdminController chce odwoływać się do metod pozostałych crudów. Nie wiem czy rozumiem dobrze Twoją propozycję ale chyba masz to na myśli co ja chce osiągnąć. Jeżeli się mylę pokaż mi przykładową implementacje
Go to the top of the page
+Quote Post
kpt_lucek
post
Post #16





Grupa: Zarejestrowani
Postów: 428
Pomógł: 77
Dołączył: 10.07.2011
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


  1. <?php
  2.  
  3. namespace Acme\DemoBundle\Manager\NewsService;
  4.  
  5. use Doctrine\ORM\EntityManager;
  6.  
  7. class NewsService
  8. {
  9. /**
  10.   * @var EntityManager
  11.   */
  12. protected $em;
  13.  
  14. /**
  15.   * @param EntityManager $entityManager
  16.   */
  17. public function __construct(EntityManager $entityManager)
  18. {
  19. $this->em = $entityManager;
  20. }
  21.  
  22. /**
  23.   * @param NewsInterface $news
  24.   * @return $this
  25.   */
  26. public function acceptNews(NewsInterface $news)
  27. {
  28. $news->setAccepted(true);
  29.  
  30. return $this;
  31. }
  32.  
  33. /**
  34.   * @param NewsInterface $news
  35.   * @return $this
  36.   */
  37. public function removeNews(NewsInterface $news)
  38. {
  39. $this->em->remove($news);
  40. $this->em->flush($news);
  41.  
  42. return $this;
  43. }
  44. }

  1. #services.yml
  2. services:
  3. news_service:
  4. class: Acme\DemoBundle\Manager\NewsService
  5. arguments: [ @doctrine.orm.entity_manager ]

  1. <?php
  2.  
  3. namespace Acme\DemoBundle\Controller;
  4.  
  5. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  6. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
  7. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  8. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  9. use Symfony\Component\HttpFoundation\Request;
  10. use Acme\DemoBundle\Entity\News;
  11.  
  12. class AdminController extends Controller
  13. {
  14. /**
  15.   * @Route("/news-accept/{news}", name="accept_news", requirements={"news": "\d+"})
  16.   * @ParamConverter("news", class="AcmeDemoBundle:News")
  17.   * @Template()
  18.   * @param News $news
  19.   * @return array
  20.   */
  21. public function acceptNewsAction(News $news)
  22. {
  23. $newsService = $this->get('news_service')->acceptNews($news);
  24. return [];
  25. }
  26. }


Chociażby tak, wtedy masz nie zależne usługi operujące na jakiejś konretnej funkcjonalności, chociażby News'ach.

Zobacz dodatkowo:
@see
@see

#pisane z palca#
Go to the top of the page
+Quote Post
Matrix12
post
Post #17





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 22.03.2015

Ostrzeżenie: (0%)
-----


Powiedz mi w routingu lepiej używać adnotacji czy jednak config.yml ?
Go to the top of the page
+Quote Post
kpt_lucek
post
Post #18





Grupa: Zarejestrowani
Postów: 428
Pomógł: 77
Dołączył: 10.07.2011
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Wedle uznania, ja używam adnotacji, bo jest wszystko w jednym i łatwiej tym zarządzać
Go to the top of the page
+Quote Post
Matrix12
post
Post #19





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 22.03.2015

Ostrzeżenie: (0%)
-----


Teraz spotykam się z kolejnym ograniczeniem.. Zastanowiłem się i wydaje mi się, że źle podchodzę do tego.. Bo mam kilka bundli np. NewsBundle(który zawiera kontrolery etc.) itd. Chciałem zarządzać tym z poziomu AdminBundle.. Ale czy to wgl ma sens ? Bo z drugiej strony w każdym z bundli w kontrolerach mam metody które są odpowiedzialne za administrowanie danymi bundlami. Czy może nie lepiej zrobić to tak, aby nie powielać dodatkowo kodu tylko w każdym z bundli dodać routing np. /panel/admin/delete( i to będzie odpowiedzialne za usunięcie newsla z bazy)? Jak to rozwiązać. Proszę o wskazówki !
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 10.01.2026 - 00:28