2012-10-07 4 views
12

In Controller mich schaffen und mein Modell verwenden, soService Locator in Zend Framework 2

public function getAlbumTable() 
{ 
    if (!$this->albumTable) { 
     $sm = $this->getServiceLocator(); 
     $this->albumTable = $sm->get('Album\Model\AlbumTable'); 
    } 
    return $this->albumTable; 
} 

Wie verwende ich diesen globalen Service Locator an einer anderen Stelle meines Projektes, beispielsweise in dem anderen Modell, und nicht nur in irgendeinem Controller?

Сonfiguration der Verbindung zur Datenbank in der Datei definiert ist: my_project/config/autoload/global.php

Danke.

Antwort

6

Entschieden. Damit. Zur Lösung der Aufgabe von Klassen von Modellen muss die Schnittstelle ServiceLocatorAwareInterface implementiert werden. So wird der ServiceManager automatisch in Ihrem Modell injiziert. Siehe das vorherige Beispiel.

Für Formulare und andere Objekte Ihrer Anwendung geeignete Methode vorgeschlagen hier http://michaelgallego.fr/blog/?p=205 Sie können eine Basisklasse Formular erweitert Baseform und implementiert ServiceManagerAwareInterface, von denen Sie seine Formulare in der Anwendung erben.

namespace Common\Form; 

use Zend\Form\Form as BaseForm; 
use Zend\ServiceManager\ServiceManager; 
use Zend\ServiceManager\ServiceManagerAwareInterface; 

class Form extends BaseForm implements ServiceManagerAwareInterface 
{ 
    /** 
    * @var ServiceManager 
    */ 
    protected $serviceManager; 

    /** 
    * Init the form 
    */ 
    public function init() 
    { 
    } 

    /** 
    * @param ServiceManager $serviceManager 
    * @return Form 
    */ 
    public function setServiceManager(ServiceManager $serviceManager) 
    { 
     $this->serviceManager = $serviceManager; 

     // Call the init function of the form once the service manager is set 
     $this->init(); 

     return $this; 
    } 
} 

Zur Injektion des Ziels des Servicemanagers war automatisch in der Datei module.config.php in Abschnitt service_manager Sie

'invokables' => array(
    'Album\Form\AlbumForm' => 'Album\Form\AlbumForm', 
), 

Dann in Ihrem Controller zu schreiben, dann können Sie ein Formular erstellen, so

$form = $this->getServiceLocator()->get('Album\Form\AlbumForm'); 

Das Formular enthält ein Objekt ServiceManager, das andere Abhängigkeiten zulassen wird.

Vielen Dank für Ihre Hilfe.

15

Zend MVC wird die ServiceLocator-Instanz in eine Klasse einfügen, die Zend \ ServiceManager \ ServiceLocatorAwareInterface implementiert. Eine einfache Implementierung für eine Modelltabelle sieht wie folgt aus:

+0

Nun, danke, es funktioniert wirklich! Und wie man mit anderen Klassen als Klasse sein soll, erweitert AbstractTableGateway zum Beispiel mit den Klassen der Forms (extends Zend \ Form), den Klassen der Elemente (extends Zend \ Form \ Element)? Wie benutze ich den ServiceLocator?Oder verwenden Sie es dort ist eine schlechte Idee? .. – Eremite

+0

Wenn die Klasse durch den ServiceManager erstellt wird, die die bewusste Schnittstelle implementiert, dann wird der ServiceManager injiziert, nachdem die Klasse erstellt wurde. Für Zend \ Form kann dies ein Problem darstellen, da die meisten Elemente im Konstruktor erstellt werden (SM wird nach diesem Punkt eingefügt). Es gibt einen Blogbeitrag, der darüber spricht - http://www.michaelgallego.fr/blog/?p=205 – DrBeza

+0

Ich habe den Kern Ihrer Methode verstanden. Es ist nicht klar, wie ServiceManager automatisch die setServiceManager-Methode aufruft, wenn Sie eine Instanz der form extends Form-Klasse erstellen, die Sie in Ihrem Blog beschreiben. Sie schreiben die Notwendigkeit, das Array 'invokables' für den ServiceManager zu verwenden, könnten Sie im Detail sagen, wie dies zu tun ist. Vielen Dank. – Eremite

0

getServicelocator() macht Fehler. Es braucht also einen alternativen Weg. Und erstreckt sich AbstractTableGateway oder ServiceLocatorAwareInterface haben Fehler.

Factory-Implementierung wird Controller helfen, Objekte zu bekommen.

* User Beispielcode wird Album ähnlich sein.

1) Factory-Klasse (RegisterControllerFactory.php) * kopiert Funktion create in Controller

namespace Users\Controller\Factory; 

use Users\Controller\RegisterController; 

use Zend\ServiceManager\FactoryInterface; 
use Zend\ServiceManager\ServiceLocatorInterface; 
use Zend\ServiceManager\Exception\ServiceNotCreatedException; 


class RegisterControllerFactory 
{ 

    public function __invoke($serviceLocator) 
    { 
    $sm = $serviceLocator; 
    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); 

    $resultSetPrototype = new \Zend\Db\ResultSet\ResultSet(); 
    $resultSetPrototype->setArrayObjectPrototype(new \Users\Model\User); 
    $tableGateway  = new \Zend\Db\TableGateway\TableGateway('user' /* table name */, $dbAdapter, null, $resultSetPrototype); 

    $user = new \Users\Model\User(); 
    $userTable = new \Users\Model\UserTable($tableGateway); 

    $controller = new RegisterController($userTable, $serviceLocator); 
    return $controller; 

    } 
} 

2) Controller (RegisterController) Namespace Users \-Controller;

use Zend\Mvc\Controller\AbstractActionController; 
use Zend\View\Model\ViewModel; 

use Users\Form\RegisterForm; 
use Users\Form\RegisterFilter; 

use Users\Model\User; 
use Users\Model\UserTable; 

use Zend\ServiceManager\ServiceLocatorInterface; 

class RegisterController extends AbstractActionController 
{ 
    protected $userTable; 
    protected $serviceManager; 

    public function __construct(UserTable $userTable, ServiceLocatorInterface  $serviceManager) 
{ 
    $this->userTable = $userTable; 
    $this->serviceManager = $serviceManager; 
} 

public function indexAction() 
{ 
    $form = new RegisterForm(); 
    $viewModel = new ViewModel(array('form' => $form)); 
    return $viewModel; 
} 

public function processAction() 
{ 
    if (!$this->request->isPost()) { 
     return $this->redirect()->toRoute(NULL , array( 
        'controller' => 'register', 
        'action' => 'index' 
       )); 
    } 

    $post = $this->request->getPost(); 

    $form = new RegisterForm(); 
    $inputFilter = new RegisterFilter(); 
    $form->setInputFilter($inputFilter); 

    $form->setData($post); 
    if (!$form->isValid()) { 
     $model = new ViewModel(array(
      'error' => true, 
      'form' => $form, 
     )); 
     $model->setTemplate('users/register/index'); 
     return $model; 
    } 

    // Create user 
    $this->createUser($form->getData()); 

    return $this->redirect()->toRoute(NULL , array( 
        'controller' => 'register', 
        'action' => 'confirm' 
       )); 
} 

public function confirmAction() 
{ 
    $viewModel = new ViewModel(); 
    return $viewModel; 
} 

protected function createUser(array $data) 
{ /*able to delete or modify */ 
    $sm = $this->serviceManager; 
    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); 

    $resultSetPrototype = new \Zend\Db\ResultSet\ResultSet(); 
    $resultSetPrototype->setArrayObjectPrototype(new \Users\Model\User); 
    $tableGateway  = new \Zend\Db\TableGateway\TableGateway('user' /* table name */, $dbAdapter, null, $resultSetPrototype); 

    $user = new User(); 
    $user->exchangeArray($data); 

    $userTable = new UserTable($tableGateway); 
    $userTable->saveUser($user); 

    return true; 
    } 
} 

3) module.config.php

return array( 
    'controllers' => array(
    'invokables' => array(
     'Users\Controller\Index' => 'Users\Controller\IndexController', 
     'Users\Controller\login' => 'Users\Controller\LoginController', 
     //delete 'Users\Controller\Register' 
    ), 
    'factories' => array(
      'Users\Controller\Register' =>  'Users\Controller\Factory\RegisterControllerFactory', 
    ),  
),