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

Shortest url

Hello Phalcon team...

I need to make route as:

https://www.sitename.com/lang/controller

if controller doesnot exists the controller will be as parameter.

my route looks like:

 $router = new \Phalcon\Mvc\Router(false);
 $router->removeExtraSlashes(true);
 $router->setDefaultNamespace('Multiple\Frontend\Controllers');
 $router->setUriSource($router::URI_SOURCE_SERVER_REQUEST_URI);
 // NEWS ROUTING

 $router->setDefaultModule("frontend");

 $router->notFound(array(
     'module'     => 'frontend',
     "controller" => "index",
     "action" => "show404"
 ));

 $router->add('/', [
     'module'     => 'frontend',
     'controller' => 'index',
     'action' => 'index',
 ])->setName('frontend'); 

 $router->add('/{language:[a-z]{2}}', [
     'module'     => 'frontend',
     'controller' => 'index',
     'action'     => 'index',
 ])->setName('frontend-index-lang');

 $router->add('/{language:[a-z]{2}}/:controller', [
     'module'     => 'frontend',
     'controller' => 2,
     'action'     => 'index',
     'params'    => 2,
 ])->setName('frontend-controller');

 $router->add('/{language:[a-z]{2}}/:controller/:action', [
     'module'     => 'frontend',
     'controller' => 2,
     'action'     => 3,
     'params'    =>3,
 ])->setName('frontend-action');

 $router->add('/{language:[a-z]{2}}/:controller/:action/:params', [
     'module'     => 'frontend',
     'controller' => 2,
     'action'     => 3,
     'params'     => 4,
 ])->setName('frontend-params');
edited Apr '20

So you want, for example, sitename.com/lang/users to be routed to the users controller, unless the users controller doesn't exist, then you want the router to dispatch LangController::indexAction with "users" as the parameter - where "users" can be anything?

I'm not sure you can do that exclusively and flexibly in the router. You could make a route for /lang/[anything] high up in the file, then below that, make unique routes for every controller - but that doesn't seem too flexible.

What may work is updating your IndexController::show404 method. That method gets called whenever a route isn't matched, so /lang/users should get directed there. Before you show the 404, pull apart the URL and if the first part is lang, forward the request to LangController

Also, I updated your post to have proper syntax highlighting. Feel free to "Edit" your post to see what I did.

edited Apr '20

Thank you Dylan

maybe i solve the problem by the code..

$router->add('/{language:[a-z]{2}}/:controller', [

                'module'     => 'frontend',
                'controller' => 2,
                'action'     => 'index',
                'params'    => 2,
            ])->beforeMatch(function($uri, $route) use ($di) {
                $allowed = ['contact', 'index', 'sitemap', 'special', 'tag'];
                if (preg_match($route->getCompiledPattern(), $uri, $matches) && !in_array($matches[2], $allowed)){
                    $route->reConfigure($route->getPattern(), array(
                        'module'     => 'frontend',
                        'controller' => 'index',
                        'action'     => 'details',
                        'params'    => 2,
                    ));
                }
                return true;
            });

I didn't found the function get all active controllers.. I wrote manually

$allowed = ['contact', 'index', 'sitemap', 'special', 'tag'];

if controller is in the array returns simple route syntax or not wecan use reConfigure function

Do you think the code is correct??

we are using multi-module MVC structure...

Yeah, I think that would work.