Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [ZendFramework][ZF2][ZendFramework2] Factories i ServiceManager - do czego uzyc
Forum PHP.pl > Forum > PHP > Frameworki
elmozaur
Witam.
Zaczynam dopiero przygode z zendem i przerabiajac tutorial o dodawaniu albumow plytowych do bazy nasunelo mi sie pytanie:

1) co to jest service manager, do czego można go używać, co można do niego dodawać (doczytalem ze factories mozna tu podpiac ale dlaczego questionmark.gif?)?
2) co to jest factory/factories (w tutorialach to ma cos wspolnego z konfigami ale nie jestem pewien)questionmark.gif?

pytania o podstawy zenda2 zadawać tutaj czy w "przedszkolu" ?

za cierpliwosc i zrozumienie dziekuje i pozdrawiam
Grzegorz
RiE
Service Manager jest oparty o wzorzec Service Locator i jest to mechanizm slużący do pobierania innych obiektów. Używa się go w module.config.php lub Module.php i składa się z 7 typów(kategorii).

1. abstract_factories pod tym kluczem definiuje się klasy, które muszą implementować ZendServiceManagerAbstractFactoryInterface. Rzadko używane.
2. aliases nadaje klasie alias, np:
  1. 'aliases' => array(
  2. 'translator' => 'MvcTranslator',
  3. ),


Teraz jesteśmy w stanie się odwołać za pomocą

  1. $this->getServiceLocator()->get('translator')


3. factories deklaruje klasy, które powinny implementować Zend/ServiceManager/FactoryInterface. Dość często używane. Np:

  1. 'factories' => array(
  2. 'UserTable' => function($sm) {
  3. $tableGateway = $sm->get('UserTableGateway');
  4. $table = new UserTable($tableGateway);
  5. return $table;
  6. },


Jeżeli klasa ma konstruktor lub jeśli potrzebujemy dodać do klasy obiekty innej klasy to używamy do tego celu właśnie klucza factories. Obiekt jest inicjowany od razu- w momencie kiedy jest wczytywany do Service Managera.

4. invokables definiujemy klasy, które nie mają konstruktora lub jeśli nie musimy z niego(konstruktora) skorzystać. Również dość często używane, jak chociażby dla naszych klas kontrolera. Np:

  1. 'invokables' => array(
  2. 'Application\Controller\Index' => 'Application\Controller\IndexController',
  3. )


Klasy pod tym kluczem są inicjowane dopiero w momencie odwołania się do danego klucza, a nie w momencie 'pobrania' przez ServiceManager

5. services służy głównie do deklarowania 'service'ów' lub klas, które są już zainicjowane. Np:

  1. 'services' => array(
  2. 'name' => $zmienna,
  3. ),


6. initializers nie miałem okazji jeszcze z tego korzystać. Ten klucz definiuje callback, który jest uruchamiany za każdym razem gdy jest tworzony obiekt, w ten sposób jeśli obiekt spełnia wymagania(np. implementuje konkretny interfejs) jeśtemy w stanie 'wstrzepić' inny obiekt.

  1. 'initializers' => array(
  2. function ($instance, $sm) {
  3. if ($instance instanceof AuthorizeAwareInterface) {
  4. $instance->setAuthorizeService($sm->get('auth_service'));
  5. }
  6. }
  7. )


7. shared domyślnie wszystkie service'y od ServiceManagera są 'shared', czyli pracujemy na tym samym obiekcie. Tutaj jesteśmy w stanie to zmienić, gdy np. chcemy żeby za każdym razem był tworzony nowy obiekt.

  1. $table1 = $this->getServiceLocator()->get('UserTable');
  2. $table2 = $this->getServiceLocator()->get('UserTable');
  3. // table1 i table2 to ten sam obiekt


Gdy dodamy:

  1. 'shared' => array(
  2. 'UserTable' => false,
  3. ),


  1. $table1 = $this->getServiceLocator()->get('UserTable');
  2. $table2 = $this->getServiceLocator()->get('UserTable');
  3. // table1 i table2 to różne obiekty



Jak napisałem na początku, Service Manager służy do łatwego dostępu do obiektów. Np. wyobraźmy sobie że tylko dla pewnej akcji chcesz dodać jakiś plik js, możesz to zrobić tak:

  1.  
  2. public function addAction()
  3. {
  4. $this->getServiceLocator()
  5. ->get('viewhelpermanager')
  6. ->get('HeadScript')
  7. ->appendFile('/js/ckeditor/ckeditor.js','text/javascript');
  8. }


Tutaj za pomocą Service Managera dostajemy się do obiektu HeadScript i dzięki temu jesteśmy w stanie dodać plik js z poziomu akcji kontrolera

Najczęśniej używane są factories i invokables. Co to są factories to napisałem wyżej, ale może dodam jeszcze jeden przykład żeby lepiej zobrazować co robi.

Mamy klasę:

  1. class HelloService
  2. {
  3. public function sayHello()
  4. {
  5. return 'Hello World';
  6. }
  7. }


I załóżmy że chcemy wyświetlić w widoku to co zwraca metoda sayHello().
Możemy to zrobić na dwa sposoby.

1. Invokables

W pliku Module.php dodajemy:

  1. public function getServiceConfig()
  2. {
  3. return array(
  4. 'invokables' => array(
  5. 'HelloService'
  6. => 'Helloworld\Service\HelloService'
  7. )
  8. );
  9. }


I teraz w akcji:

  1. public function indexAction()
  2. {
  3. $hello = $this->getServiceLocator()
  4. ->get('HelloService');
  5.  
  6. return new ViewModel(
  7. array('hello' => $hello->sayHello())
  8. );
  9. }


Najpierw dodajmy do ServiceManagera klasę HelloService, później w akcji pobieramy z Service Managera i odwołujemy się do metody sayHello(). Trochę to toporne i niewydajne.

2. Factories

  1.  
  2. 'factories' => array(
  3. 'Helloworld\Controller\Index' => function($sm) {
  4. $controller = new Helloworld\Controller\IndexController();
  5.  
  6. $controller->setHelloService(
  7. $sm->getServiceLocator()
  8. ->get('HelloService')
  9. );
  10.  
  11. return $controller;
  12. }
  13. )


I w akcji:

  1. class IndexController extends AbstractActionController
  2. {
  3. private $helloService;
  4.  
  5. public function indexAction()
  6. {
  7.  
  8. return new ViewModel(
  9. 'hello' => $this->helloService->sayHello()
  10. )
  11. );
  12. }
  13.  
  14. public function setHelloService($service)
  15. {
  16. $this->helloService = $service;
  17. }
  18. }


Tym sposobem dodajemy obiekt klasy HelloService do kontrolera w Service Managerze i teraz w akcji nie musimy pobierać tego obiektu, tylko bezpośrednio możemy na nim pracować. Bardziej czytelniejsze rozwiązanie, wydajne i zalecane.
elmozaur
RiE: dla Ciebie powini stworzyć przycisk "Bardzo pomógł"
irmidjusz
zgadzam się z elmozaurem smile.gif
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.