Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cakephp 3 routing with language parameter

I'm trying to convert cakephp 2.x to 3.x. I was using Router::connect() rules, but I try to convert them to scope version.

Regarding to myold routing rule, in config/routes.php I added this.

  Router::defaultRouteClass('Route');
  Router::scope('/', function ($routes) {

    $routes->connect('/:language/:controller/:action/*', ['language' => 'ar|de|en|fr']);
    $routes->connect('/:language/:controller', ['action' => 'index', 'language' => 'ar|de|en|fr']);
    $routes->connect('/:language', ['controller' => 'Mydefault', 'action' => 'index', 'language' => 'ar|de|en|fr']);

    $routes->redirect('/gohere/*', ['controller' => 'Mycontroller', 'action' => 'myaction'], ['persist' => array('username')]);

    $routes->connect('/', ['controller' => 'Mydefault', 'action' => 'index']);

    $routes->fallbacks('InflectedRoute');
});
  • But this fails in example.com/en/works. I get this error: Error: worksController could not be found. Because my controller file is WorksController.php.

Does controller name part hanged to sentence casein cakephp 3 ? http://book.cakephp.org/3.0/en/intro/conventions.html#controller-conventions

  • Also example.com/foo/bar gives this error: Error: barController could not be found.. But foo is controller and bar is action.

How can I fix this routing problem ?

Edit:
Changing Route::defaultRouteClass('Route') to Route::defaultRouteClass('InflectedRoute') solved problem 1. But problem 2 exists.

like image 818
trante Avatar asked Jul 12 '15 07:07

trante


2 Answers

Options, such as route element patterns, must be passed via the third argument of Router::connect(), the $options argument.

This route:

$routes->connect(
    '/:language/:controller',
    ['action' => 'index', 'language' => 'ar|de|en|fr'
]);

will catch your /foo/bar URL, it will match foo for the :language element, and bar for the :controller element. Basically the language key in the URL array will be treated as the default value, and it will always be overwritten by the :language element value.

The correct way of defining the route is:

$routes->connect(
    '/:language/:controller',
    ['action' => 'index'],
    ['language' => 'ar|de|en|fr']
);

The other routes need to be adapted accordingly.

See also Cookbook > Routing > Connecting Routes

like image 104
ndm Avatar answered Oct 19 '22 03:10

ndm


The best way is using Routing scopes

<?php
$builder = function ($routes) {
    $routes->connect('/:action/*');
};
$scopes = function ($routes) use ($builder) {
    $routes->scope('/questions', ['controller' => 'Questions'], $builder);
    $routes->scope('/answers', ['controller' => 'Answers'], $builder);
};

$languages = ['en', 'es', 'pt'];
foreach ($languages as $lang) {
    Router::scope("/$lang", ['lang' => $lang], $scopes);
}

Router::addUrlFilter(function ($params, $request) {
    if ($request->param('lang')) {
        $params['lang'] = $request->param('lang');
    }
    return $params;
});

Code taken from:

https://github.com/steinkel/cakefest2015/blob/c3403729d7b97015a409c36cf85be9b0cc5c76ef/cakefest/config/routes.php

like image 29
José Lorenzo Rodríguez Avatar answered Oct 19 '22 01:10

José Lorenzo Rodríguez