How to include module's .phtml from layout?

zend-view

#1

Hello.

Idea:

<?php // layout.phtml

...

<body>

<?= $this->partial('sidebar') ?>

<?= $this->content ?>

</body>

?>

Problem: partial() does not work.

How to include static .phtml from current module directory?
Zend Framework 3.


#2

The partial actually works, this is from my codebase:

somewhere in the layout.phtml
<?= $this->partial('partial/js_translations.tpl.php'); ?>

#3

Works for Application, not modules.


#4

Try following.
Add in module’s config key to the partial file

'view_manager'    => [
    'template_path_stack' => [
        __DIR__ . '/../view',
    ],
    'template_map'        => [
        'partial-key'     => __DIR__ . '/../view/module/partial/partial.phtml',
    ],
],

and than in layout.phtml

<?= $this->partial('partial-key'); ?>

#5

I predict this will only work for the last module in the global /config/modules.config.php. I want each module to have a separate partial.phtml.


#6

Actually it will be merged, so just add different key in every config array.


#7

I will be compelled to pass it in each method of the controller? is there an easy way to get the name of the current module in the layout?


#8

Yes there is :slight_smile: I created a module for that zend-current-route
so you can just install it and use:

$this->currentRoute()->getModule(); // return current module name

#9

Never!

An option is a listener. Short example:

Listener:

namespace Application\Listener;

use Zend\EventManager\AbstractListenerAggregate;
use Zend\EventManager\EventManagerInterface;
use Zend\Mvc\MvcEvent;

class MyListener extends AbstractListenerAggregate
{
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $this->listeners['addSidebar'] = $events->attach(
            MvcEvent::EVENT_RENDER,
            [
                $this,
                'addSidebar',
            ]
        );
    }

    public function addSidebar(MvcEvent $event)
    {
        $serviceManager = $event->getApplication()->getServiceManager();

        /** @var \Zend\Mvc\View\Http\ViewManager $viewManager */
        $viewManager = $serviceManager->get('ViewManager');
        $viewManager->getViewModel()->addChild(
            (new \Zend\View\Model\ViewModel(
                [
                    'foo' => 'bar',
                ]
            ))->setTemplate('sidebar'),
            'sidebar'
        );
    }
}

Add to your module config:

'service_manager' => [
    'factories'  => [
        // ...
        Application\Listener\MyListener::class => Zend\ServiceManager\Factory\InvokableFactory::class,
    ],
],

Add to your module class:

public function onBootstrap(EventInterface $e)
{
    $application = $e->getApplication();

    $aggregate = $application->getServiceManager()->get(
        MyListener::class
    );
    $aggregate->attach($application->getEventManager());

    return [];
}

Create the sidebar.phtml and add in your layout:

<?= $this->sidebar ?>

#10

Not bad.
May be need zend-module-config? Where module’s settings will overlap Application.


#11

Thank you!
Don’t you think that’s too much?


#12

It’s your choice. You can copy the same code in every controller or create one listener. :wink:

With this type of listener you can also create a guard that verifies user access, you can set ACL to the navigation view helpers and so on.

Btw. this is only one idea / suggestion.


#13

I cant understand, view helper have not access to Request object?


#14

This is not a view helper, it is a listener which can be added in a mvc-based application. More infos can be found in the “mvc event” section of the documentation.

Btw. you can copy the code, add to your application and test it yourself.


#15

About listener i understand.
Is it possible to solve this problem by view helper?
“Display” task by view way.
Thank you!


#16

I cant understand, view helper have not access to Request object?

Yes it has.

You can use module that I sent you - just “plug & play it”.

I certainly encourage you to take a look at the code.
In the CurrentRouteFactory.php you can see

$routeMatch = $container->get('Application')->getMvcEvent()->getRouteMatch();

this is what you need