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

Wild card routing in multi module application

Hey Guys

Here is my router in my app/Bootstrap.php file

    protected function router()
    {

        $this->di->set('router', function() {
            $router = new Router(false);

            $router->setDefaults(array(
                'module' => $this->config->router->default->module,
                'controller' => $this->config->router->default->controller,
                'action' => $this->config->router->default->action
            ));

            /*
             * All defined routes are traversed in reverse order until Phalcon\Mvc\Router
             * finds the one that matches the given URI and processes it, while ignoring the rest.
             */
            $frontend = new \Phalcon\Mvc\Router\Group(array(
                'module' => 'frontend',
            ));

            // Allow camel case controller and action name that will be accessed via dashes
            $frontend->add('/([a-zA-Z\-]+)/([a-zA-Z\-]+)/:params', array(
                'controller' => 1,
                'action' => 2,
                'params' => 3
            ))->convert('action', function($action) {
                return \Phalcon\Text::lower(\Phalcon\Text::camelize($action));
            });

            // Mount a group of routes for frontend
            $router->mount($frontend);

            /**
             * Define routes for each module
             */
            //foreach ($this->getModules() as $module => $options) {
            foreach (array('core', 'backend' => array('alias' => 'admin'), 'api') as $module => $options) {
                $group = new \Phalcon\Mvc\Router\Group(array(
                    'module' => $module,
                ));

                $group->setPrefix('/' . (isset($options['alias']) ? $options['alias'] : $module));

                // Allow camel case controller and action name that will be accessed via dashes
                $group->add('/([a-zA-Z\-]+)/([a-zA-Z\-]+)/:params', array(
                    'controller' => 1,
                    'action' => 2,
                    'params' => 3
                ))->convert('action', function($action) {
                    return \Phalcon\Text::lower(\Phalcon\Text::camelize($action));
                });

                // Mount a group of routes for some module
                $router->mount($group);
            }

            return $router;
        });
    }

Here is my directory structure: https://pastie.org/9709545

My issues is when I go to https://example.com/api/sms/send it gives me a 404 page (hits frontend/Module.php when it should be hitting api/v1.0.x/Module.php)

When I do have a SmsController -> send action?

Anyone know how to route multi modules correctly?

Thanks



98.9k

I think the problem is

foreach (array('core', 'backend' => array('alias' => 'admin'), 'api') as $module => $options) {

Note the routes generated, keys/values in the inner array do not produce the expected routes:

/([a-zA-Z\-]+)/([a-zA-Z\-]+)/:params
/0/([a-zA-Z\-]+)/([a-zA-Z\-]+)/:params
/admin/([a-zA-Z\-]+)/([a-zA-Z\-]+)/:params
/1/([a-zA-Z\-]+)/([a-zA-Z\-]+)/:params


7.9k
$di->set(
            "router",
            function () use ($config, $modules) {
                $router = new Router();
                $router->setDefaultModule("App\\Modules\\Admin\\Module");
                $router->setDefaultController('index');
                $router->setDefaultAction('index');
                $router->removeExtraSlashes(true);

                // Load routing file
                $files = array_diff(scandir(APP_PATH . "Config/routing/"), array('..', '.'));

                foreach ($files as $file) {
                    $explode = explode(".", $file);
                    $class = "App\\Config\\Routing\\" . $explode[0];
                    $router->mount(new $class());
                }

                return $router;
            }
        );

and here is Admin routing

namespace App\Config\Routing;

use Phalcon\Mvc\Router\Group;

class Admin extends Group
{
    public function initialize()
    {
        $this->setPaths(
            array(
                "module" => "Admin",
                "namespace" => "Nanomites\\Modules\\Admin\\Controllers"
            )
        );

        $this->setPrefix("/admin");

        $this->add(
            '',
            array(
                'action' => 'index'
            )
        );
    }
}

that code above will provide this url structure https://www.awesome.dev/module/controller/params



7.9k

Its up to you,

you have just edit this code if your path changed

$files = array_diff(scandir("folder/path/to/routing file), array('..', '.'));

here is my folder structure

routing file located in app/Config/routing

Then below checks seems to fix the issue though I think I will look to implement @Prasetyo solution as it is a lot neater.

Thanks Guys :)

    foreach (array('core', 'backend' => array('alias' => 'admin'), 'api') as $module => $options) {

                // If an alias is set use that
                if (isset($options['alias']) && !empty($options['alias'])) {
                    $module = $options['alias'];
                }

                // If module is an int then $options contains the module name
                if (is_int($module)) {
                    $module = $options;
                }

                $group = new \Phalcon\Mvc\Router\Group(array(
                    'module' => $module,
                ));

                $group->setPrefix('/' . (isset($options['alias']) ? $options['alias'] : $module));

                // Allow camel case controller and action name that will be accessed via dashes
                $group->add('/([a-zA-Z\-]+)/([a-zA-Z\-]+)/:params', array(
                    'controller' => 1,
                    'action' => 2,
                    'params' => 3
                ))->convert('action', function($action) {
                    return \Phalcon\Text::lower(\Phalcon\Text::camelize($action));
                });

                // Mount a group of routes for some module
                $router->mount($group);
            }