We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Passing variable to view from beforeExecuteRoute() event

I have defined my dispatcher service with following event attachment:

$di->setShared('dispatcher', function() use ($di) {
    $eventsManager = new EventsManager();
    $eventsManagerHandler = new EventManagerHandler($di);
    $eventsManager->attach('dispatch', $eventsManagerHandler);

    $dispatcher = new Dispatcher();
    $dispatcher->setDefaultNamespace('Test\Modules\Frontend\Controllers');
    $dispatcher->setEventsManager($eventsManager);

    return $dispatcher;
});

In EventManagerHandler class, I have defined beforeExecuteRoute() function:

public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher) : bool
{
    $controllerName = $dispatcher->getControllerName();
    $actionName     = $dispatcher->getActionName();

    // Only check permissions on private controllers
    if ($dispatcher->getDI()->getAcl()->isPrivate($controllerName)) {
        // Get the current identity
        $identity = $dispatcher->getDI()->getAuth()->getIdentity();

        // If there is no identity available the user is redirected to index/index
        if (!is_array($identity)) {
            $dispatcher->getDI()->getFlash()->error('You need to sign in to access the page.');

            $forwardUrl = array(
                'controller' => 'index',
                'action'     => 'index'
            );

            $request = new Request();
            $uri = $request->getURI();

            if($uri !== '/' || $uri !== '/dashboard' || $uri !== '/dashboard/index')
                $forwardUrl['params'] = array('_returnUrl' => $uri);

            $dispatcher->forward($forwardUrl);
            return false;
        }

        // Set User Menu
        $menu = Menus::findFirstByProfileId($dispatcher->getDI()->getAuth()->getProfileId());
        if ($menu) {
            $dispatcher->getDI()->getView()->menu = json_decode(json_decode($menu->menu), true, 512);
        }

        // Check if the user have permission to the current option
        if (!$dispatcher->getDI()->getAcl()->isAllowed($dispatcher->getDI()->getAuth()->getProfile(), $controllerName, $actionName)) {

            // Access Denied Error Page
            $dispatcher->forward([
                'controller' => 'errors',
                'action'     => 'show401'
            ]);

            return false;
        }
    }

    return true;
}

Here I want to pass $menu to the view. How can I achieve this? Currently, $dispatcher->getDI()->getView() has no action defined so it does not attach the variable to current action.



8.4k

could extending Phalcon\Di\Injectable from EventManagerHandler could do the trick ? or perhaps Phalcon\Mvc\View::setVars() or Phalcon\Mvc\View::setVar()



5.9k
Accepted
answer
edited Apr '20

In my EventManagerHandler

public function beforeRender(Event $event, View $view)
{
    // Only check permissions on private controllers
    if ($view->getDI()->getAcl()->isPrivate($view->getControllerName())) {
        // Get the current identity
        $identity = $view->getDI()->getAuth()->getIdentity();

        // If there is no identity available the user is redirected to index/index
        if (is_array($identity)) {
            // Set User Menu
            $menu = Menus::findFirstByProfileId($identity['profileId']);
            if ($menu) {
                //$dispatcher->getDI()->getView()->menu = json_decode(json_decode($menu->menu), true, 512);
                $view->setVar('menu', json_decode(json_decode($menu->menu), true, 512));
            }
        }
    }
}

and then in View Service attached event manager:

$di->set('view', function () {
    $manager = new Manager();

    $eventsManagerHandler = new EventManagerHandler();
    $manager->attach(
        'view',
        $eventsManagerHandler
    );

    $view = new View();
    $view->setDI($this);
    $view->setViewsDir(__DIR__ . '/views/');
    $view->setLayoutsDir(__DIR__ . '/views/layouts/');

    $view->registerEngines([
        '.volt'  => 'voltShared',
        '.phtml' => PhpEngine::class
    ]);
    $view->setEventsManager($manager);
    return $view;
});