Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Can I use dispatcher::forward across sub-controllers?

I would like to use a modified simple-subcontroller pattern. It has the following structure.

project/
   app/
      controllers/
         admin/
            IndexController.php
         user/
            IdexController.php
            LoginController.php
      ...
      plugins/
         SecurityPlugin.php

(bsed on the following) https://github.com/phalcon/mvc/tree/master/simple-subcontrollers

Of those who can access user, we want to make sure that only a specific person can access admin and below, so when accessing admin directly, we want to forward to Login under user. For that purpose, I wrote the following SecurityPlugin.

class SecurityPlugin extends \Phalcon\Mvc\User\Plugin
{
    public function beforeExecuteRoute($event, $dispatcher)
    {
    ......
            $dispatcher->forward(['controller' => 'login', 'action' => 'index',]);
            // the result is the same
            // $dispatcher->forward(['controller' => 'user\login', 'action' => 'index',]);
            return false;
        }
}

However, it seems to look for it under admin and will not find LoginController. Isn't it possible to use it like this?

Maybe it should be like this (although not done yet)?

project/
   app/
      controllers/
         user/
            IdexController.php
            LoginController.php
            admin/
               IndexController.php
      ...
      plugins/
         SecurityPlugin.php


5.6k
Accepted
answer

In the forward method try add namespace

edited Sep '19

If you have modules set-up, the docs advise to use dispatch:beforeForward:

https://docs.phalcon.io/3.4/en/dispatcher#using-the-events-manager

Otherwise, use @olegatro 's suggestion!

Thank you for your reply.

Is namespace a fully qualified name?

$dispatcher->forward(['controller' => 'user\login', 'action' => 'index',]);

In this case as well, ".../admin/user/login/index " seems to be looking for.

Modules is not used this time. But I didn't know "dispatch:beforeForward". I saw that forward could only specify controller/action, and thought that module could not be used. I would like to use it at the next opportunity.

Yes, the namespace is the full path and should be registered either in Phalcon\Loader or some other autoloading mechanism.

I try this.

$dispatcher->forward(['controller' => 'Myapp\Controllers\User\Login', 'action' => 'index',]);

displayed this

Myapp\Controllers\Admin\Myapp\Controllers\User\LoginController handler class cannot be loaded
edited Sep '19

Of course it is already registered.

config/config.php

return new Phalcon\Config([
    'version' => '1.0',
......
    'registerNamespaces' => [
        'Myapp\Controllers'        => APP_PATH . '/controllers/',
        'Myapp\Controllers\User' => APP_PATH . '/controllers/user',
        'Myapp\Controllers\Admin' => APP_PATH . '/controllers/admin',
        'Myapp\Models'             => APP_PATH . '/models/',
        'Myapp\Lib'                => APP_PATH . '/library/',
        'Myapp\Plugins'            => APP_PATH . '/plugins/',
    ],

and registered

$di->setShared('config', function () {
    return include APP_PATH . '/config/config.php';
});

$loader = new \Phalcon\Loader();
$loader->registerNamespaces((array)$di->get('config')->get('registerNamespaces'))->register();

try this

$this->dispatcher->forward([
    'namespace' => 'Myapp\Controllers\User\\',
    'controller' => 'login',
    'action' => 'index'
]);
return false;

https://github.com/phalcon/cphalcon/blob/v3.4.0/phalcon/dispatcher.zep#L872

I had a misunderstanding. That was the meaning of "add namespace". This worked as expected, thank you very much.