Search code examples
phpzend-framework2dependencieszend-framework3zf3

What is the best way to refactor ZF2 ServiceLocatorAwareInterface to work with ZF3 in view helper?


I have view helper from ZF2 that doesn't work anymore with ZF3 because of ServiceLocatorAwareInterface deprecation.

What's the proper way to refactor that class:

<?php

namespace Site\View\Helper;

use Zend\View\Helper\AbstractHelper;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class SlidersList extends AbstractHelper implements ServiceLocatorAwareInterface 
{
    protected $_serviceLocator;

    public function __invoke() 
    {
        return $this->getView()->render(
            'partials/sliders', 
            array('sliders' => $this->getServiceLocator()->getServiceLocator()->get('Sliders/Model/Table/SlidersTable')->fetchAll(true))
        );
    }

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

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

Should I use view helper factory to inject service locator and if yes, how it should be done?


Solution

  • No, you should NOT use a factory to inject a ServiceLocator instance (never), instead you should inject the dependencies directly. In your case you should inject your SlidersTable service. You should do like this:

    1) Make your class constructor dependent on your SlidersTable service:

    <?php
    
    namespace Site\View\Helper;
    
    use Zend\View\Helper\AbstractHelper;
    use Sliders\Model\Table\SlidersTable;
    
    class SlidersList extends AbstractHelper
    {
        protected $slidersTable;
    
        public function __construct(SlidersTable $slidersTable) 
        {
            return $this->slidersTable = $slidersTable;
        }
    
        public function __invoke() 
        {
            return $this->getView()->render(
                'partials/sliders', 
                array('sliders' => $this->slidersTable->fetchAll(true))
            );
        }
    }
    

    2) Create a factory where you inject your dependency:

    <?php
    namespace Site\View\Helper\Factory;
    
    use Site\View\Helper\SlidersList;
    use Interop\Container\ContainerInterface;
    use Zend\ServiceManager\Factory\FactoryInterface;
    
    class SlidersListFactory implements FactoryInterface
    {
        /**
         * @param ContainerInterface $container
         * @param string $requestedName
         * @param array|null $options
         * @return mixed
         */
        public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
        {
            $serviceManager = container
            $slidersTable= $container->get('Sliders/Model/Table/SlidersTable');
            return new SlidersList($slidersTable);
        }
    }
    

    3) register your view helper inside your module.config.php:

    //...
    
    'view_helpers' => array(
        'factories' => array(
            'Site\View\Helper\SlidersList' =>  'Site\View\Helper\Factory\SlidersListFactory'
        )
    ),
    
    //...