12

In controller I create and use my model so

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

How do I use this global Service Locator in another place of my project, for example, in the other model, and not only in any controller?

Сonfiguration of the connection to the database is defined in the file: my_project/config/autoload/global.php

Thank you.

Uwe L. Korn
  • 8,080
  • 1
  • 30
  • 42
Eremite
  • 481
  • 1
  • 8
  • 18

3 Answers3

15

Zend MVC will inject the ServiceLocator instance into a class implementing Zend\ServiceManager\ServiceLocatorAwareInterface. A simple implementation for a model table looks like the following:

<?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');
    //...
  }
}
Elvan
  • 621
  • 3
  • 4
  • Well, thank you, it really works! And how to be with classes other than class extends AbstractTableGateway, for example, with the classes of the forms (extends Zend\Form), the classes of the elements (extends Zend\Form\Element)? How to use the ServiceLocator there? Or use it there is a bad idea?.. – Eremite Oct 07 '12 at 18:57
  • If the class is created through the ServiceManager that implements the aware interface then the ServiceManager is injected after the class is created. For Zend\Form this can pose an issue as much of the elements set-up is usually done in the constructor (SM injected after this point). There is a blog post talking about this - http://www.michaelgallego.fr/blog/?p=205 – DrBeza Oct 08 '12 at 10:07
  • I understood the gist of your method. It is not clear just how to make ServiceManager automatically call the setServiceManager method when you create an instance of the form extends Form class which you describe in your blog. You write the need to use the array 'invokables' for the ServiceManager, could you say in detail how to do this. Thank you. – Eremite Oct 08 '12 at 11:44
6

Decided. So. For solving the task of classes of models must implement the interface ServiceLocatorAwareInterface. So injection ServiceManager will happen in your model automatically. See the previous example.

For forms and other objects of your application suitable method proposed here http://michaelgallego.fr/blog/?p=205 You can to create a base class form extends BaseForm and implements ServiceManagerAwareInterface, from which you will inherit its forms in the application.

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

To injection of the object of the ServiceManager was automatically in the file module.config.php in section service_manager you need to write

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

Then in your controller, you can create a form so

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

The form will contain an object ServiceManager, which will allow other dependencies.

Thanks all for your help.

Eremite
  • 481
  • 1
  • 8
  • 18
0

getServicelocator() makes error. So it needs alternative way. And extends AbstractTableGateway or ServiceLocatorAwareInterface have errors.

Factory implementation will help Controller to get objects.

*User sample code will be similar to album.

1) factory class ( RegisterControllerFactory.php) * copied function createUser 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',
   ),       
),
fantaghirocco
  • 4,761
  • 6
  • 38
  • 48
Marcus
  • 1
  • 1