What is the best project structure with admin panel using zend-mvc?

I need separated modules for admin panel.
Also, separate template.
How did you organised your admin panel?
All routes should located after localhost/admin/
Is this right thought? I am looking for best practices.

module/AdminModule/src/Listener/LayoutListener.php

declare(strict_types=1);

namespace AdminModule\Listener;

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

class LayoutListener extends AbstractListenerAggregate
{
    /**
     * @param EventManagerInterface $events
     * @param int $priority
     * @return void
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $events->getSharedManager()->attach(
            AbstractController::class,
            MvcEvent::EVENT_DISPATCH,
            [$this, 'changeLayout'],
            99
        );
    }

    /**
     * @param MvcEvent $e
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function changeLayout(MvcEvent $e)
    {
        $controller = get_class($e->getTarget());
        $moduleName = substr($controller, 0, strpos($controller, '\\'));
        $config     = $e->getApplication()->getServiceManager()->get('config');
        if (isset($config['module_layouts'][$moduleName])) {
            $e->getTarget()->layout($config['module_layouts'][$moduleName]);
        }
    }
}

module/AdminModule/config/module.config.php

    return [
        'listeners' => [
            Listener\LayoutListener::class,
        ],
    ],

config/autoload/layout-change.global.php

return [
    'module_layouts' => [
        'Application'     => 'layout/layout',
        'AdminModule'     => 'layout/layout-admin',
    ],
];

module/Application/view/layout/layout.phtml
module/AdminModule/view/layout/layout-admin.phtml

1 Like

Can I have some global listener? I mean, listener that is located in some /config/listener.global.php and not inside module.

Can I attach admin layout to the parent “/admin/” router (not to the AdminModule)?

I think you can intercept the URI in the event listener:

$event->getApplication()->getRequest()->getUri();