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

Routing for a multi-module project

Hey guys, i'm kinda super new to phalcon and trying to make work one thing.

I have a multi-module project and being completly unsatisfied by defining all routes at once. So I'd like to register routes for each module.

Got simple router setting in my index:

$di->set('router', function () {
    $router = new Router(false);
    $router->setDefaultModule('upload');
    return $router;
});

After this in my module in registerServices function i'm trying to set some another router somehow like this:

$di->get('router')->addGet('/', [someparams]);

But actually all routes that being registered inside the module is completly ignored and never matching.

I only may assume that by the momemnt of loading a module routing is already loaded. Is it any other explanation or I'm doing something wrong?

thanks in advance.



85.5k
edited Nov '15

hey, my code: // or docs here: https://docs.phalcon.io/en/latest/reference/routing.html#groups-of-routes

application.php


$this->di->set('router', new ApplicationRouter(), true);

//call this function after you are done registering services
public function _registerModules($modules, $merge = null)   {
        parent::registerModules($modules, $merge);

        $loader = new Loader();
        $modules = $this->getModules();

        /**
         * Iterate the application modules and register the routes
         * by calling the initRoutes method of the Module class.
         * We need to auto load the class
         */
        foreach ($modules as $module) {
            $className = $module['className'];

            if (!class_exists($className, false)) {
                $loader->registerClasses([ $className => $module['path'] ], true)->register()->autoLoad($className);
            }

            $className::initRoutes($this->di);
        }
    }

ApplicationRouter.php

class ApplicationRouter extends Router
{
    /**
     * Creates a new instance of ApplicationRouter class and defines standard application routes
     * @param boolean $defaultRoutes
     */
    public function __construct($defaultRoutes = false)
    {
        parent::__construct($defaultRoutes);

        $this->removeExtraSlashes(true);

        /**
         * Controller and action always default to 'index'
         */
        $this->setDefaults([
            'controller' => 'index',
            'action' => 'index'
        ]);

        $this->add('/', array(
            'module' => 'home',
            'controller' => 'index',
            'action' => 'index',
            'namespace' => '\Home\Controllers\\'
        ))->setName('default');

        $this->add('/logout', array(
            'module' => 'home',
            'controller' => 'index',
            'action' => 'logout',
            'namespace' => '\Home\Controllers\\'
        ))->setName('default-logout');

        /**
         * Add default not found route
         */
        $this->notFound([
            'module' => 'home',
            'controller' => 'index',
            'action' => 'notFound',
            'namespace' => '\Home\Controllers\\'
        ]);
    }
}

my Module.php


public static function initRoutes(\Phalcon\DiInterface $di) {
        $loader = new Loader();
        $loader->registerNamespaces([
            '\Home' => __DIR__,
            ], true)
            ->register();

        $router = $di->getRouter();
        $router->mount(new ModuleRoutes());
    }

ModuleRoutes.php

class ModuleRoutes extends \Phalcon\Mvc\Router\Group
{
    /**
     * Initialize the router group for the Home module
     */
    public function initialize() {

        $this->setPrefix('/home');

        /**
         * Configure the instance
         */
        $this->setPaths([
            'module' => 'home',
            'controller' => 'index',
            'action' => 'index'
        ]);

        /**
         * Default route: 'home-root'
         */
        $this->addGet('', [])
            ->setName('home-root');

        /**
         * Controller route: 'home-controller'
         */
        $this->addGet('/:controller', ['controller' => 1])
            ->setName('home-controller');

        /**
         * Action route: 'home-action'
         */
        $this->addGet('/:controller/:action/:params', [
                'controller' => 1,
                'action' => 2,
                'params' => 3
            ])
            ->setName('home-action');
    }
}

Modules are runned after routing handling and dispatching system.

I'm using custom routes in module. But they are set in module/config/router.php and before handling application I check all modules for this config and putting it to router.

If you find another way, please let me know.

You have to register routes beforce dispatching/registering modules. Im using RouteGroup, loading all those RouteGroup classes in loader, and then checking for modules and mount each routegroup from it to my router.



1.8k
edited Nov '15

hey guys, thank you for comments / tips.

After some brain-destructing I came up with this solution:

$di->get('router')->clear();

class MyApp extends Application
{
    public function registerModules(array $modules, $merge = null)
    {
        parent::registerModules($modules, $merge);

        foreach ($this->getModules() as $module) {
            $routesClass = $module['className'] . 'Routes';
            $routesPath = $module['directory'] . '/ModuleRoutes.php';

            $loader = new \Phalcon\Loader();

            $loader->registerClasses(
                [
                    $routesClass => $routesPath
                ]
            )->register();

            $this->di->get('router')->mount(new $routesClass());
        }
    }
}

It's not any kind of elegant but works for now.