Router

Zemit will use the Phalcon MVC Router or the CLI Router.

Phalcon will pass every defined router parameters to the dispatcher's handler's action method. However, we found this behavior quite unstable when mixing parameters with integer and string keys because the parameters order will be mixed making the method parameters unusable in different situations and with different scenarios.

If you are using the Zemit\Dispatcher\AbstractDispatcher, which is the default one used by default in Zemit,only the parameters with integer keys will be passed to the action method parameters.

Default Routes

Zemit will automatically add new routes. If the bootstrap mode is set to Console, the Zemit\Cli\Router will be used, otherwise the Zemit\Bootstrap\Router will be used by default.

Default MVC Routes

Route nameRoute path

default

/

default-controller

/:controller

default-controller-action

/:controller/:action

default-controller-action-params

/:controller/:action/:params

Localization MVC Routes

The default MVC Routes will allow loop through the allowed locale to define their respective default routes as well.

NameRoute path

locale

/:locale

locale-controller

/:locale/:controller

locale-controller-action

/:locale/:controller/:action

locale-controller-action-params

/:locale/:controller/:action/:params

Note: the :locale placeholder is not a valid placeholder. Refer yourself to the official Phalcon Router Documentation for the list of valid placeholders to use.

Zemit let you define the allowed locale, only the locale "en" is set into the zemit configuration by default. Zemit will define the specific routes for each allowed locale defined within the config.

NameRoute path

en

/en

en-controller

/en/:controller

en-controller-action

/en/:controller/:action

en-controller-action-params

/en/:controller/:action/:params

If you add new locale to the LOCALE_ALLOWED configuration, zemit will add their respective default routes as well. As an example, this configuration below:

// .env
// $config->locale->allowed
// $config->locale->default

LOCALE_ALLOWED=fr,en
LOCALE_DEFAULT=en

Will generate the new default routes routes for these names below:

NameRoute path

fr

/fr

fr-controller

/fr/:controller

fr-controller-action

/fr/:controller/:action

fr-controller-aciton-params

/fr/:controller/:action/:params

Creating your own Routers

MVC Router

// ./app/Bootstrap/Router.php
namespace App\Bootstrap;

/**
 * Class Router
 * @package App\Bootstrap
 */
class Router extends \Zemit\Bootstrap\Router
{
    public function __construct($defaultRoutes = true, $application = null)
    {
        // Call the parent if you want to create the default Zemit Routes
        parent::__construct($defaultRoutes, $application);
        
        // add your custom route here
        // ...
    }
}

CLI Router

// ./app/Bootstrap/CliRouter.php
namespace App\Bootstrap;

/**
 * Class Router
 * @package App\Bootstrap
 */
class CliRouter extends \Zemit\Cli\Router
{
    public function __construct($defaultRoutes = true, $application = null)
    {
        // Call the parent if you want to create the default Zemit Routes
        parent::__construct($defaultRoutes, $application);
        
        // add your custom route here
        // ...
    }
}

Method #1: Defining your own Router from the Bootstrap

You can define your own router directly within the Bootstrap class by initializing the $router variable.

// ./app/Bootstrap.php
namespace App;

use App\Bootstrap\Config;
use App\Bootstrap\Router;

class Bootstrap extends \Zemit\Bootstrap
{
    public function initialize(): void
    {
        $config = new Config();
        $this->setConfig($config)
        
        $router = new Router(true, $config);
        $this->setRouter($router);
    }
}

Perhaps you may want to use the initializer in this particular case so you can use the correct Router depending on the application type. The console (CLI) Application requires a different type of Router in order to work. This example below will allow your bootstrap to work while using the MVC or the CLI Phalcon Application.

d// ./app/Bootstrap.php
namespace App;

class Bootstrap extends \Zemit\Bootstrap
{    
    // Recommended way as this will work with the CLI or the MVC Application
    public function initialize()
    {
        // Set the custom routers
        $this->setRouter($this-isConsole() ?
            \App\Bootstrap\CliRouter::class :
            \App\Bootstrap\Router::class
        );
    }
}

Method #2: Loading using a custom Service Provider

This is a little bit more advanced. You could in fact avoid touching the bootstrap at all by setting your custom router service provider directly from the config.

Directly from the .env file as shown below:

# ROUTER PROVIDER
PROVIDER_ROUTER=\App\Provider\Router\ServiceProvider

Or from your own \App\Bootstrap\Config custom class. The point is to replace the default Zemit Router Service Provider with your own:

// ./app/Bootstrap/Config.php
namespace App\Bootstrap;

use Zemit\Utils\Env;

class Config extends Zemit\Bootstrap\Config
{
    public function __construct(array $data = [], bool $insensitive = true)
    {
        parent::__construct([
            // ...
            'provider' => [
                \Zemit\Provider\Router\ServiceProvider::class => Env::get('PROVIDER_ROUTER',
                    \App\Provider\Router\ServiceProvider::class
                ),
            ],
            // ...
        ]);
        // ...
    }
}

Below is an example of what your custom router service provider should look like:

// ./app/Provider/Router/ServiceProvider.php
namespace App\Provider\Router;

class ServiceProvider extends AbstractServiceProvider
{
    protected $serviceName = 'router';
    
    public function register(DiInterface $di): void
    {
        $di->setShared($this->getName(), function () use ($di) {
        
            /** @var \App\Bootstrap $bootstrap */
            $bootstrap = $di->get('bootstrap');
    
            $router = $bootstrap->router ?? $bootstrap->isConsole()
                ? new \App\Bootstrap\CliRouter(true)
                : new \App\Bootstrap\Router(true, $bootstrap->application);
            if (is_string($router) && class_exists($router)) {
                $router = new $router();
            }
            
            $defaults = $bootstrap->config->path($bootstrap->isConsole()? 'router.cli': 'router.defaults');
            $router->setDefaults($defaults? $defaults->toArray() : []);
            $router->setEventsManager($di->get('eventsManager'));
            $router->setDI($di);
            
            return $router;
        });
    }
}

Last updated