Search code examples
phpzend-framework2

ZendFramework 2 - ServiceManager in my Class


I begin to use Zend2 in my work not so long, and my question how get ServiceManager in my class "Blog". This class is contain

$this->db 
$this->logger 
$this->logger_error
$this->session
$this->filter
$this->access
$this->view 
$this->user 
$this->base_url 

many fields for work.

I use this class in Controllers and without Controller. Now I create class

class Application extends Zend\Mvc\Application
{

    static public function init()
    {
        return \Zend\Mvc\Application::init(include 'config/application.config.php');
    }
}

and use it for initialization

class Blog
{
     /**
      *  
      * @var Doctrine\DBAL\Connection 
      */
    protected $db;
    /** 
     *
     * @var Zend\Log\Logger
     */
    protected $logger;
    /** 
     *
     * @var Zend\Log\Logger
     */
    protected $logger_error;
    /**             
     *
     * @var Variable
     */
    protected $variable;
     /**
     *
     * @var \Zend\Cache\Storage\Adapter\Filesystem
     */
    protected $cache;
    /**
     *
     * @var \Zend\Session\Container
     */
    protected $session;

    function __construct()
    {
         $sm = Application::init()->getServiceManager();


        $this->db =  $sm->get('db');
        $this->logger = $sm->get("logger");
        $this->logger_error = $sm->get("logger_error");
        $this->variable = $sm->get("variable");
        $this->cache = $sm->get("cache");
        $this->session = $sm->get("session");
    }

Is it normal?


Solution

  • I would say this isn't the correct solution.

    The correct way to retrieve the service manager is by implementing the interface Zend\ServiceManager\ServiceLocatorAwareInterface in your class Blog.

    use Zend\ServiceManager\ServiceLocatorAwareInterface;
    use Zend\ServiceManager\ServiceLocatorInterface;
    
    class Blog implements ServiceLocatorAwareInterface {
    
        protected $serviceLocator;
    
        public function getServiceLocator() {
            return $this->serviceLocator;
        }
    
        public function setServiceLocator(ServiceLocatorInterface $serviceLocator) {
            $this->serviceLocator = $serviceLocator;
        }
    
    }
    

    Then you must retrieve this call through the service manager, like in the controller:

    $blog = $this->getServiceLocator()->get('namespace\of\Blog');
    

    And finally, in the configuration file (Module.php or module.config.php, you declare your class:

    // ...
    'service_manager' => array(
        'invokables' => array(
            'namespace\of\Blog' => 'namespace\of\Blog'
        )
    ),
    // ...
    

    If you need this class in a place where you don't have access to the service manager, then you are creating this class in the wrong place. Looking at the different components you are retrieving in your class (database, logs, cache, session), you are doing a lot of stuff in this class. I would suggest to split this logic in different classes and instantiate them in the module's boostrap:

    use Zend\Mvc\MvcEvent;
    
    class Module {
    
        public function onBootstrap(MvcEvent $event) {
            $serviceManager =$event->getApplication()->getServiceManager();
            $blog = $serviceManager->get('namespace\of\Blog');
        }
    
    }