Use different layout for each module

Is it possible to set up a layout for each module?

I am following an Oleg Krivtsov’s tutorial, but I don’t understand how to create a layout for each module. I’m struggling with the use of partial, helper, and listener to accomplish this.

Can you recommend any resources that provide a simple solution to my question to understand how this thing works

Thank you.

With a listener you are on the right track, because for each request it must be checked which is the target module for the current request. The configuration of all registered modules is always loaded and even cached when the application is started, therefore it needs a listener who listens for an event in the application process.
But since a layout is only needed when an output is actually rendered from the view layer, it can be started very late in the process.

The documentation of laminas-eventmanager contains a tutorial how to create a listener in a laminas-mvc based application and also the registration of the listener:

The documentation of laminas-view contains a cookbook recipe for your use case:

https://docs.laminas.dev/laminas-view/cookbook/setting-module-specific-layouts/

2 Likes

Some more tutorials which describe the integration of components into applications (e.g. cache, form, session) can be found in the tutorials section:

@Super0Yt ,

There is one simple way to change the layout for a given module which is to set the desired layout for the view that will be returned by the controller. If your controller is an extension of the AbstractController, which is the case most of the time in an MVC app, then you can use the layout() controller plugin:

$view = new ViewModel([ ...your variables...]);
$this->layout('mylayout');
return $view;

Where 'mylayout' is defined in your view stack.

This is useful if you need to change the layout for special cases where your default layout is not appropriate.

Hope this helps

1 Like

Or the view helper:

https://docs.laminas.dev/laminas-view/helpers/layout/

But the requirement in the original post, seems to be different:

I agree with you. I was just providing a quick solution just in case he was looking to do this for one module.

Don’t worry, I didn’t want to contradict you. Let’s wait and see if there is any feedback on what is really needed in the end. :smiley:

but in this case i should use $this->layout for all my controllers.
what i ask for is how to define a unique layout for each module, like @froschdesign proposethe the solution it’s by using listener and some more code that i can’t understand now and in that is the solution.
@visto9259 thank you for your solution

If you need help, just ask here.

1 Like

@Super0Yt ,

Just some guidance if you want to implement this using a listener.

You need to attach a listener to the dispatch event that is triggered by the AbstractController.

You can attach the listener to the shared event manager of the application and I suggest a priority -101 so that it is called pretty much as the last thing before rendering starts (i.e. the default layout is set, the view models have been injected, no errors were found, etc.)

Here’s a simple way of doing it:

In a Module class somewhere:

class Module 
{
    public function onBootstrap(MvcEvent $event)
    {
        $application = $event->getApplication();
        $sharedEvents = $application->getEventManager()->getSharedManager();
        $sharedEvents->attach(AbstractController::class, MvcEvent::EVENT_DISPATCH, [$this, 'setLayout'], -101);
    }

    public function setLayout(MvcEvent $event)
    {
        $controller = $event->getTarget();
        // use $controller to find the layout template that you need for the controller
        $layout = somelogic($controller);
        // use the layout() plugin to set the layout template
       $controller->layout($layout);
    }
}

This is very basic but it should give you the gist of it.

Not necessary, everything can be taken from the documentation. See the link above: “Setting module-specific Layouts”

And if you check the usage in the documentation of laminas-eventmanager, then you will see that the module class can stay nice and clean. :smiley: