Use differents layouts to differents modules zend

2020-02-12 07:08发布

问题:

I am using EdpModuleLayouts to use one layout to mobile version of my zf2 webapp and another to the "desktop" version.

The configuration in module.config.php in Application module:

...'view_manager' => array(
    'display_not_found_reason' => true,
    'display_exceptions'       => true,
    'doctype'                  => 'HTML5',
    'not_found_template'       => 'error/404',
    'exception_template'       => 'error/index',
    'template_map' => array(
        'module_layouts' => array(
            'Application' => 'layout/application',
            'User'        => 'layout/user',
        ),
        'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',
        'error/404'               => __DIR__ . '/../view/error/404.phtml',
        'error/index'             => __DIR__ . '/../view/error/index.phtml',
    ),
    'template_path_stack' => array(
        __DIR__ . '/../view',
    ),
),

Module.php of the Application module it's like this:

public function onBootstrap(MvcEvent $e)
{

    $e->getApplication()->getServiceManager()->get('translator');
    $eventManager        = $e->getApplication()->getEventManager();
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);


    $e->getApplication()->getEventManager()->getSharedManager()
    ->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', function($e) {
        $controller      = $e->getTarget();
        $controllerClass = get_class($controller);
        $moduleNamespace = substr($controllerClass, 0, strpos($controllerClass, '\\'));
        $config          = $e->getApplication()->getServiceManager()->get('config');
        if (isset($config['module_layouts'][$moduleNamespace])) {
            $controller->layout($config['module_layouts'][$moduleNamespace]);
            echo $config['module_layouts'][$moduleNamespace];
        }
    }, 100);

}

Finally, I have one layout in Application module and another in User module. At this moment every time render the layout in the User Model, even though I enter the Application url.

I stucked on this, I appreciate some help.

回答1:

I am also using EdpModuleLayouts for my multi-layout project. I think, you need to move module_layouts from module.config.php to autoload/global.php file.

This is my Module.php of the Application module :

public function onBootstrap(MvcEvent $e)
{
    $eventManager        = $e->getApplication()->getEventManager();
    $eventManager->getSharedManager()->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', function($e) {
        $controller      = $e->getTarget();
        $controllerClass = get_class($controller);
        $moduleNamespace = substr($controllerClass, 0, strpos($controllerClass, '\\'));
        $config          = $e->getApplication()->getServiceManager()->get('config');
        if (isset($config['module_layouts'][$moduleNamespace])) {
            $controller->layout($config['module_layouts'][$moduleNamespace]);
        }
    }, 100);
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);
}

This is my config\autoload\global.php :

return array(
   'db' => array(
       .........
   ),
   'service_manager' => array(
       ...........
   ),
   'module_layouts' => array(
       'Application' => 'layout/layout.phtml',
       'MyModuleName' => 'layout/mymodulename.phtml',
   ),
);

it works for me and hope it helps you.



回答2:

Update your module.config.php

'view_manager' => array(
    'template_path_stack' => array(
        'admin' => __DIR__ . '/../view',
    ),
    'template_map' => array(
        'admin/layout' => __DIR__ . '/../view/layout/layout.phtml',
    ),
),

now in module.php write following lines

use Zend\ModuleManager\ModuleManager;

public function init(ModuleManager $mm)
    {
        $mm->getEventManager()->getSharedManager()->attach(__NAMESPACE__,
        'dispatch', function($e) {
            $e->getTarget()->layout('admin/layout');
        });
    }

now create a folder layout in module's view directory and create a file with name layout.phtml and put your layout code there.



回答3:

My solution:

  1. Write controller plugin;
  2. In the plugin :

    $modNameArray = explode('\\', $event->getRouteMatch()->getParam('controller'));
    $modName = $modNameArray[0];
    $viewModel->setTemplate(strtolower($modName).'/layout');
    

to get module name, that's first directory name of your controller, in my app at least.

  1. Adjust you module.config.php

     'template_map' => array(
         //moduleName/layout => your layout path
        'auth/layout' => __DIR__ . '/../view/layout/auth.phtml',
        'auth/index/index' => __DIR__ . '/../view/auth/index/index.phtml',
        'error/404' => __DIR__ . '/../view/error/404.phtml',
        'error/index' => __DIR__ . '/../view/error/index.phtml',
    ),
    

Works for me.



回答4:

The following works for me.

The main idea is to naming the layout a different identifier rather than using a common name like 'layout/layout'. In this way when the the config will be starting to merging, it will not get lost on the way.

If I have a module name Album then I will have the following.

public function onBootstrap($e)
{
    $e->getApplication()->getEventManager()->getSharedManager()->attach('Zend\Mvc\Controller\AbstractController', 'dispatch', function($e) {
    $controller = $e->getTarget();
    $controllerClass = get_class($controller);
    $moduleNamespace = substr($controllerClass, 0, strpos($controllerClass, '\\'));
    $controller->layout($moduleNamespace . '/layout');
    }, 100);
}  

Notice that this is a little bit different compare to EdpModuleLayouts. And module.config.php I have the following relevant configuration.

'view_manager' => array(
    'display_not_found_reason' => true,
    'display_exceptions'       => true,
    'doctype'                  => 'HTML5',
    'not_found_template'       => 'error/404',
    'exception_template'       => 'error/index',
    'template_map' => array(
        'Album/layout'           => __DIR__ . '/../view/layout/layout.phtml',
        'Album/index/index' => __DIR__ . '/../view/application/index/index.phtml',
        'error/404'               => __DIR__ . '/../view/error/404.phtml',
        'error/index'             => __DIR__ . '/../view/error/index.phtml',
    ),
    'template_path_stack' => array(
        __DIR__ . '/../view',
    ),
),

And that should be working.Hope this helps :)