2013-02-14 11 views
8

Próbuję użyć Service Manager na mojej klasie encji, ale nie wiem najlepszy sposób to zrobić.Najlepszy sposób użycia ServiceManager w klasie modelu?

To proste dla kontrolera, ponieważ możemy zadzwonić do menadżera serwisu za pomocą: $ this-> getServiceLocator();

Ale w mojej klasie jednostki, nawet jeśli realizuje ServiceLocatorAwareInterface mogę retieve ServiceManager ponieważ moja klasa jednostka nie jest zadzwonić do kierownika serwisu:

Więc co jest najlepszym sposobem:

1 - Przekaż usługę serviceManager w mojej klasie encji z mojego kontrolera 2 - Za pomocą ServiceManager zbuduj moją klasę jednostek 3 - ...?

Aby jak najlepiej zrozumieć mój problem, to jest mój kod, który nie działa:

Moja klasa podmiot:

class Demande extends ArraySerializable implements InputFilterAwareInterface { 
/../ 
    public function getUserTable() { 
    if (! $this->userTable) { 

     $sm = $this->getServiceLocator();//<== doesn't work ! 
     $this->userTable = $sm->get ('Application\Model\UserTable'); 
    } 
    return $this->userTable; 
} 

Odpowiedz

18

bym nie wstrzyknąć ServiceManager do danego modelu (choć można). Wolałbym, żeby ServiceManager zbudował dla ciebie model i wstrzyknął ci wszystko, czego potrzebujesz bezpośrednio do modelu.

Usługa Config:

'factories' => array(
    'SomethingHere' => function($sm) { 
     $model= new \My\Model\Something(); 

     return $model; 
    }, 
    '\My\Model\Demande' => function($sm) { 
     $model= new \My\Model\Demande(); 
     /** 
     * Here you use the SM to inject any dependencies you need 
     * into your model/service what ever.. 
     */ 
     $model->setSomething($sm->get('SomethingHere')); 

     return $model; 
    }, 
    /** 
    * Alternatively you can provide a class implementing 
    * Zend\ServiceManager\FactoryInterface 
    * which will provide an instance for you instad of using closures 
    */ 
    '\My\Model\DemandeDefault' => '\My\Model\DemandeFactory', 

Place którykolwiek z zależnościami wewnątrz Service Manager Config, a następnie używać, aby wstrzyknąć żadnych zależności do swoich modeli, usługi itp dla Ciebie.

Przykładem klasa fabryka jeśli chcesz użyć metody fabryki zamiast zamknięć:

DemandeFactory.php

use Zend\ServiceManager\FactoryInterface; 
use Zend\ServiceManager\ServiceLocatorInterface; 

class DemandeFactory implements FactoryInterface 
{ 
    /** 
    * Create a new Instance 
    * 
    * @param ServiceLocatorInterface $serviceLocator 
    * @return Demande 
    */ 
    public function createService(ServiceLocatorInterface $serviceLocator) 
    { 
     $config = $serviceLocator->get('Config'); // if you need the config.. 
     // inject dependencies via contrustor 
     $model = new \My\Model\Demande($serviceLocator->get('SomethingHere')); 
     // or using setter if you wish. 
     //$model->setSomething($serviceLocator->get('SomethingHere')); 

     return $model; 
    } 
} 

Przykładem modelu próbujesz instancji poprzez Service Manager.

Demande.php

class Demande 
{ 
    protected $_something; 

    /** 
    * You can optionally inject your dependancies via your constructor 
    */ 
    public function __construct($something) 
    { 
     $this->setSomething($something); 
    } 

    /** 
    * Inject your dependencies via Setters 
    */ 
    public function setSomething($something) 
    { 
     $this->_something = $something; 
    } 

    // Something will be injected for you by the Service Manager 
    // so there's no need to inject the SM itself. 
} 

w kontroler:

public function getDemande() 
{ 
    if (! $this->_demande) { 
     $sm = $this->getServiceLocator(); 
     $this->_demande = $sm->get ('\My\Model\Demande'); 
    } 
    return $this->_demande; 
} 

Można wstrzyknąć SergiceManager/ServiceLocator do swoich modeli, ale wtedy Twoje modele będą zależeć od ServiceLocator.

+2

Bardzo przydatna odpowiedź! Innym powodem, dla którego nie należy wstrzykiwać ServiceManager do modelu, jest to, że nie możemy serializować naszego obiektu (z powodu zamknięć w ServiceManager). Nie możemy więc zapisywać modeli w sesji. –

+1

Jedyną rzeczą, którą należy dodać, jest to, że nie powinieneś zbytnio nadużywać "zamknięcia". Zamiast tego pisz klas fabryki. Poprawi to ogólną wydajność, ponieważ klasy będą tworzone tylko na żądanie. Wszystkie zamknięcia będą tworzone na każde żądanie. – Sam

+1

Jeszcze jedno: jeśli pewne zależności są absolutnie ** wymagane **, to bardzo zachęca się do używania '__construct()' lub zastrzyku zamiast Settera-Injection – Sam

Powiązane problemy