Подтвердить что ты не робот

Сервисный локатор в Zend Framework 2

В контроллере я создаю и использую мою модель, поэтому

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

Как использовать этот глобальный локатор сервисов в другом месте моего проекта, например, в другой модели, а не только на любом контроллере?

Конфигурация соединения с базой данных определяется в файле: my_project/config/autoload/global.php

Спасибо.

4b9b3361

Ответ 1

Решил. Так. Для решения задачи классов моделей необходимо реализовать интерфейс ServiceLocatorAwareInterface. Таким образом, приложение ServiceManager будет выполняться автоматически в вашей модели. См. Предыдущий пример.

Для форм и других объектов вашего приложения здесь предложен подходящий метод http://michaelgallego.fr/blog/?p=205. Вы можете создать форму базового класса, которая расширяет BaseForm и реализует ServiceManagerAwareInterface, из которого вы наследуете его формы в приложении.

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;
    }
}

Для инъекции объекта ServiceManager автоматически в файле module.config.php в разделе service_manager вам нужно написать

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

Затем в вашем контроллере вы можете создать форму, чтобы

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

Форма будет содержать объект ServiceManager, который позволит другие зависимости.

Спасибо всем за вашу помощь.

Ответ 2

Zend MVC вставляет экземпляр ServiceLocator в класс, реализующий Zend\ServiceManager\ServiceLocatorAwareInterface. Простая реализация для таблицы моделей выглядит следующим образом:

<?php
use Zend\Db\TableGateway\AbstractTableGateway;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class UserTable extends AbstractTableGateway implements ServiceLocatorAwareInterface {
  protected $serviceLocator;

  public function setServiceLocator(ServiceLocatorInterface $serviceLocator) {
    $this->serviceLocator = $serviceLocator;
  }

  public function getServiceLocator() {
    return $this->serviceLocator;
  }

  // now instance of Service Locator is ready to use
  public function someMethod() {
    $table = $this->serviceLocator->get('Album\Model\AlbumTable');
    //...
  }
}

Ответ 3

getServicelocator() делает ошибку. Поэтому он нуждается в альтернативном пути. И расширения AbstractTableGateway или ServiceLocatorAwareInterface имеют ошибки.

Factory реализация поможет контроллеру получить объекты.

* Пример кода пользователя будет похож на альбом.

1) factory class (RegisterControllerFactory.php) * скопированная функция createUser в контроллере

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) контроллер (RegisterController)   namespace Пользователи \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',
   ),       
),