Cakephp 3 routing with language parameter

喜欢而已 提交于 2019-12-01 01:31:30

问题


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.


回答1:


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.

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




回答2:


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




回答3:


Extending on default router from CakePHP 3 application skeleton

original routes.php removed comments

<?php

use Cake\Routing\RouteBuilder;
use Cake\Routing\Router;
use Cake\Routing\Route\DashedRoute;

Router::defaultRouteClass(DashedRoute::class);

Router::scope('/', function (RouteBuilder $routes) {
    $routes->applyMiddleware('csrf');
    $routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
    $routes->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display']);
    $routes->fallbacks(DashedRoute::class);
});

modified with language from defined set

<?php

use Cake\Routing\RouteBuilder;
use Cake\Routing\Router;
use Cake\Routing\Route\DashedRoute;

Router::defaultRouteClass(DashedRoute::class);

$routerCallback = function (RouteBuilder $routes) {
    $routes->applyMiddleware('csrf');
    $routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
    $routes->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display']);
    $routes->fallbacks(DashedRoute::class);
};

// support only for 3 languages, other language will throw 404/NotFoundException
// or will cause different routing problem based on your routes
Router::scope('/', $routerCallback);
foreach (["en", "fr", "de"] as $language) {
    Router::scope('/' . $language, ['language' => $language], $routerCallback);
}

// to access the language param, or default to 'en', use 
// $this->request->getParam('language', 'en')
// from AppController, PagesController, etc...



回答4:


rooter.php

$routes->connect('/:lang/:controller/:action',[],[ 'lang' => '[a-z]{2}','pass' => ['lang']]);
$routes->connect('/:lang/', ['controller' => 'Pages', 'action' => 'index'],[ 'lang' => '[a-z]{2}','pass' => ['lang']]); 
$routes->connect('/:lang/index', ['controller' => 'Pages', 'action' => 'index'],[ 'lang' => '[a-z]{2}','pass' => ['lang']]); 
$routes->connect('/:lang/pages/*', ['controller' => 'Pages', 'action' => 'index'],[ 'lang' => '[a-z]{2}','pass' => ['lang']]);
$routes->connect('/:lang/contact', ['controller' => 'Pages', 'action' => 'contact'],[ 'lang' => '[a-z]{2}','pass' => ['lang']]);
$routes->connect('/:lang/about', ['controller' => 'Pages', 'action' => 'about'],[ 'lang' => '[a-z]{2}','pass' => ['lang']]);

Class Appcontroller public function beforeFilter(Event $event) { $this->Auth->allow(['']);

    if(isset($this->request->params['pass'][0]))
    $lang = $this->request->params['pass'][0];
    else $lang = 'en';
    I18n::locale($lang);

}



来源:https://stackoverflow.com/questions/31365260/cakephp-3-routing-with-language-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!