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

Is it possible to dynamically add routes after set router to the app?

Is it possible to dynamically add routes after set router to the app? Something like this: $di->set('router', require (ROOT_PATH . '/common/config/routes.php')); ... ... ... $router = $di->get('router'); $router->add(...);



368
edited Oct '14

eg: routes.php

$routes = array(
     "/admin/users/my-profile" => array(
        "controller" => "users",
        "action"     => "profile",
    ), 
     "/admin/users/change-password" => array(
        "controller" => "users",
        "action"     => "changePassword",
    )
);

return $route;

You can include that file

$routes = include('routes.php');

In di

$di->set('router', function(){
 $router = new \Phalcon\Mvc\Router();
 foreach($routes as $route=> $rull){
    $router->add($route,$rull);
 }
 return $router;
});


5.5k

In prev post i mean, that i want redefine some exist route action or add some new route actions to exist router defenition.



98.9k

Yes, but why do you want to do that?

Inside a controller or view you can do:

$this->router->add('..', array(...));
edited Mar '14

@relot can you give us an example on how/why this is needed? What do you have in mind?

For me

/login -> controller => 'session', 'action' => 'login'

is pretty much static through the application. I don't understand the need to change it to say

/login -> controller => 'session', 'action' => 'otherlogin'

after the application is dispatched.

Am I missing something?



5.5k

I want to do different routes to different modules in multi module application. And it must be active only routes, which relating to the active module. Or: i have some common routes to whole app, and i want to add some new routes to common routes for each active module. Sorry for my eng:)



98.9k
Accepted
answer

Routes need to be globally available before dispatch any module, even if they're only going to be used in a specific module. There is no a second dispatch after load a module so adding routes in the module initialization will not produce the expected result.



5.5k

Oh, so bad. Thx anyway.

How about because you would like to store routes in a database as you are expecting paths to be added by content changes like in a CMS? for a reason as to why you might want to have this feature.

edited Mar '14

You can manage to accomplish to build routes from many route config file (you will dispatch in modules). I just started a Project with Phalcon, a new experience, I'm used to ZF2. I just wanted to reproduce a file structure I know. My project is structured like that :

/
/Config
    /application.config.php
/Module
    /Main
        /config
            /route.config.php
        /src
            /Conroller
                /IndexController.php
        /view
        /Module.php
 /Public
    /index.php
 /Vendor

in /Config/applicaiton.config.phpI put the module declaration as follow :

return array(
    'module' => array(
        'Main' => array(
            'className' => 'Main\Module',
            'path'      => '../Module/Main/Module.php',
        ),
    ),
);

in Module/Main/config/route.config.php Routes are described :

return array(
    "home" => array(
        "pattern" => "/",
        "default" => array(
            "module"        => "Main",
            "controller"    => "Index",
            "action"        => "index",
        ),
    ),
);

That is the basic stucture I chose, but the challenge is to load routes before declaring Controllers in bootstrap index.php. With the following bootstrap, routes will be loaded only for registered modules in Config/application.config.php

    $di = new FactoryDefault();

    // Import Application Configuration
    $appConfig = new \Phalcon\Config(require __DIR__ . '/../Config/application.config.php');

    // Include router config file : Module/ModuleName/config/route.config.php
    // for each module
    $routerConfig = new \Phalcon\Config();
    foreach ($appConfig['module'] as $module) {
        $dir = __DIR__ . "/" . preg_replace("/\/Module.php$/", "", $module['path']) . '/config';
        if (is_dir($dir)) {
            if (file_exists($dir . '/route.config.php')) {
                $config = new \Phalcon\Config\Adapter\Php($dir . '/route.config.php');
                $routerConfig->merge($config);
            }
        }
    }
    $routerConfig = $routerConfig->toArray();
    // Set Router with merged config
    $di->set('router', function() use ($routerConfig){
        $router = new \Phalcon\Mvc\Router();
        foreach ($routerConfig as $routeName => $routeDefinition) {
            if (!array_key_exists('pattern', $routeDefinition)) {
                throw new RuntimeException("Bad route definition, key 'pattern' is missing for route named '{$routeName}'");
            }
            if (!array_key_exists('default', $routeDefinition)) {
                $routeDefinition['default'] = null;
            }
            if (!array_key_exists('verbs', $routeDefinition)) {
                $routeDefinition['verbs'] = null;
            }
            $router->add($routeDefinition['pattern'], $routeDefinition['default'], $routeDefinition['verbs'])
                ->setName($routeName);
        }
        return $router;
    });

    //Create an application
    $application = new Application($di);

    // Register the installed modules
    $application->registerModules($appConfig['module']->toArray());

Now that all routes for my modules are set, I delegate the bootstrap to the Module.php concerned. This is a generic Module.php file, only the namespace must change.

<?php

namespace Main;

use Phalcon\Loader;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\ModuleDefinitionInterface;
use Phalcon\Mvc\View;

class Module implements ModuleDefinitionInterface
{

    public function registerAutoloaders($dependencyInjector) {
        $loader = new Loader();
        $loader->registerNamespaces(array(
            __NAMESPACE__  => __DIR__ . "/src",
        ));
        $loader->register();
    }

    public function registerServices($dependencyInjector) {
        //Registering a dispatcher
        $dependencyInjector->set('dispatcher', function() {
            $dispatcher = new Dispatcher();
            $dispatcher->setDefaultNamespace(__NAMESPACE__ . "\Controller");
            return $dispatcher;
        });

        //Registering the view component
        $dependencyInjector->set('view', function() {
            $view = new View();
            $view->setViewsDir(__DIR__ . "/view");
            return $view;
        });        
    }

}