Search code examples
zend-frameworkviewzend-framework3

Reassign template in custom directory path


I'm trying to update the view model template to a template in a custom structure.

First, I merged the following view_manager config into the service manager config with this code:

$config = ArrayUtils::merge($config,$selConf);
$this->serviceManager->setAllowOverride(true);
$this->serviceManager->setService('Config',$config);
$this->serviceManager->setAllowOverride(false);

This is what was merged, with the request being publicweb as the module, index as the controller, and index as the action:

 array (size=1)
  'view_manager' => 
    array (size=2)
      'template_map' => 
    array (size=1)
      'publicweb/index/index' => string '/srv/app/client/design/gopher/publicweb/index/index/template.phtml' (length=95)
      'template_path_stack' => 
    array (size=1)
      0 => string '/srv/app/client/design/gopher' (length=58)

Finally, I executed this code:

$view = $e->getViewModel();
$view->setTemplate('publicweb/index/index');

And the results are not correct.

I also tried :

$view = $e->getViewModel();
$view->setTemplate('publicweb/index/index/template');

And the results are not correct, throwing exception Unable to render template

I pushed the template path stack /srv/app/client/design/gopher onto the beginning of the template_stack_path array so it can find that first and its still not working correctly.

Not sure whats going on. Also to note, this is being executed as an event with:

$events->getSharedManager()->attach('Zend\Mvc\Controller\AbstractController',
        MvcEvent::EVENT_DISPATCH,[$this,'assignTemplates'],500);

from the Application Module

It should be noted im also adding JS and CSS Files from the view helper within the renderer within the viewhelperpluginmanager from this event:

 $events->getSharedManager()->attach('Zend\Mvc\Controller\AbstractController',
        MvcEvent::EVENT_DISPATCH,[$this,'hydrateJsAssets'],500);

And Also id need to make sure i can also use a custom layout from that directory.

UPDATE

I was able to get it working by:

    public function onMergeConfig(ModuleEvent $event){
        parent::onMergeConfig($event);  
        $configListener = $event->getConfigListener();
        $sm = $event->getParam('ServiceManager');
        $config = $configListener->getMergedConfig(false);
        $selConf = [
            'view_manager' => [
                'template_map'=>[
                    'publicweb/index/index' => '/srv/app/client/design/gopher/publicweb/index/index/template.phtml',
                ]
            ]
        ];
        $config = ArrayUtils::merge($config,$selConf);
        $configListener->setMergedConfig($config);
        $event->setConfigListener($configListener);
        $sm->setAllowOverride(true);
        $sm->setService('Config',$config);
        $sm->setAllowOverride(false);
    }

Via

 public function init(ModuleManager $moduleManager) {
    $events = $moduleManager->getEventManager();
    $events->attach(ModuleEvent::EVENT_MERGE_CONFIG,[$this,'onMergeConfig']);        
}

But the issue is this is hardcoded and i dont have access to the request so i cannot get the module,controller,action


Solution

  • Your updated solution is not needed, you can provide configuration from the module using config provider feature, it will be picked up by module manager and merged on merge config event:

    namespace Foo;
    
    use Zend\Mvc\Controller\AbstractActionController;
    use Zend\Mvc\MvcEvent;
    
    class Module
    {
        public function getConfig()
        {
            return [
                'view_manager' => [
                    'template_map' => [
                        // change to application root relative paths
                        'publicweb/index/index' => '/srv/app/client/design/gopher/publicweb/index/index/template.phtml',
                    ],
                ],
            ];
        }
    
        /**
         * Register layout listener
         */
        public function onBootstrap(MvcEvent $e)
        {
            $e->getApplication()
                ->getEventManager()
                ->getSharedManager()
                ->attach(AbstractActionController::class, 'dispatch', function($e) {
                    $controller = $e->getTarget();
                    $controllerClass = get_class($controller);
                    $config = $e->getApplication()
                        ->getServiceManager()
                        ->get('config');
                    // do your logic here, you have controller class and config
                    if ($logic) {
                        $controller->layout($layout);
                    }
                }, 100);
        }
    }
    

    Nice article about changing layouts, applies to zf3 as well https://www.masterzendframework.com/views/change-layout-controllers-actions-zend-framework-2/