Search code examples
javascriptajaxservicezend-framework2viewhelper

ZF2 : How to call a view helper in a service?


I need use a view helper (myPaginationControl) in this service:

/.../
class TotoDisplayService implements ServiceLocatorAwareInterface
{
    public function getReponse ($paginator)
    {
        $tab = '<table>';
        /.../

        $tab .= myPaginationControl($paginator, 'sliding','pagination_control_file',array('route' => 'paginator'));

        /.../
        foreach ($paginator as $t) {
            //something to list : THIS WORKS
        }
        $tab .= '</table>';

        return array(
            'result' => $tab
        );
    }
/.../

This service is called by this controller:

public function displayAction()
{
    $em = $this->getEntityManager();
        // query to database
    $q1 = $this->serviceLocator->get('toto_list_service');
    $rep1 = $q1->getReponse($em);

    $paginator = new PaginatorZF(new DoctrinePaginator(new PaginatorORM($rep1)));
    $paginator->setCurrentPageNumber ($this->params()->fromRoute('page', 1))->setItemCountPerPage(25);

        // prepares something to display with javascript
    $q2 = $this->serviceLocator->get('toto_display_service');
    $rep2 = $q2->getReponse($paginator);

        // return to javascript 
    return new JsonModel(
        $rep2
    );
}

Here is MyPaginationControl (the same as paginationControl, I did it for test)

use Zend\View\Helper\AbstractHelper;

class MyPaginationControl extends AbstractHelper
{
    public function __invoke($a, $b, $c, $d)
    {
        $PaginationControl = $this->getView()->plugin('paginationcontrol');

        return $PaginationControl($a,$b,$c,$d);
    }
}

Here is module.config.php

    'service_manager' => array(
        'invokables' => array (
            'toto_list_service' => 'Com\Service\Invokable\TotoListService',
            'toto_display_service' => 'Com\Service\Invokable\TotoDisplayService'
        )
    ),
    'view_helpers' => array(
        'invokables' => array(
            'myPaginationControl' => 'Com\View\Helper\MyPaginationControl',
            ),
    ),

Here is module.php (nothing special)

class Module implements AutoloaderProviderInterface
{
    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\ClassMapAutoloader' => array(
                __DIR__ . '/autoload_classmap.php',
            ),
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                   __NAMESPACE__ => __DIR__ . '/src/' . tr_replace('\\', '/' , __NAMESPACE__),
                ),
            ),
        );
    }

    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }

    public function onBootstrap(MvcEvent $e)
    {
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
    }
}

Here the error message: Call to undefined function Com\Service\Invokable\MyPaginationControl() in D:\Zend\Apache2\htdocs\Gestion\module\Com\src\Com\Service\Invokable\TotoDisplayService.php

And this controller is called by javascript (AJAX). All works when I comment the line : $tab .= myPaginationControl(...

I verified that my view helper myPaginationControl perfectly works when I use it in a phtml file.

Thank you in advance for your help.


Solution

  • In your controller do this:

    $this->getServiceLocator()->get('ViewHelperManager')->get("toto_display_service")

    Please, not that this is not the best solution. Instead I would suggest you to pass the viewhelper with a factory via the __constructor(){}

    namespace Application\Factory\Controller;
    
    use Application\Controller\MyClassNameController;
    use Zend\Mvc\Controller\ControllerManager;
    
    class MyCLassNameFactory
    {
        /**
         * @{inheritDoc}
         */
        public function __invoke(ControllerManager $controllerManager)
        {
            $serviceLocator = $controllerManager->getServiceLocator();
    
            $controller = new MyClassNameController(
                $serviceLocator->get('ViewHelperManager')->get('toto_display_service');
            );
    
            return $controller;
        }
    }
    

    and in MyClassController

    class MyClassNameController extends ADD_ANOTHER_CONTROLLER
    {
       private $todoService = null;
    
        public function __construct($todoService = null)
        {
           $this->todoService = $todoService
        }
    }
    

    After that add the config in Module.php or module.config.php. I prefer the module.config.php file.

    'controllers' => [
            'factories' => [
                'Application\Controller\MyClassName'        => 'Application\Factory\Controller\MyClassNameFactory'
        ],
    ],
    

    Don't forget to remove the controller from the invokables or it won't work and you will get a collision

    Edit

    $tab .= myPaginationControl should be $tab .= new myPaginationControl or $tab .= $this->myPaginationControl

    if the above doesn't work dump the contents of $this->getServiceLocator()->get('ViewHelperManager') find myPaginationControl and call it like that $this->getServiceLocator()->get('ViewHelperManager')->get("myPaginationControl");