【问题标题】:Cakephp 3 routing with language parameterCakephp 3 带有语言参数的路由
【发布时间】:2015-09-30 15:33:54
【问题描述】:

我正在尝试将 cakephp 2.x 转换为 3.x。我正在使用Router::connect() 规则,但我尝试将它们转换为范围版本。

关于myold的路由规则,我在config/routes.php添加了这个。

  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');
});
  • 但这在example.com/en/works 中失败了。我收到此错误:Error: worksController could not be found. 因为我的控制器文件是WorksController.php

控制器名称部分是否挂在句子 casein cakephp 3 上? http://book.cakephp.org/3.0/en/intro/conventions.html#controller-conventions

  • 同样example.com/foo/bar 给出此错误:Error: barController could not be found.。但是foo 是控制器,bar 是操作。

如何解决这个路由问题?

编辑:
Route::defaultRouteClass('Route') 更改为Route::defaultRouteClass('InflectedRoute') 解决了问题1。但问题2 存在。

【问题讨论】:

  • 您的 routes.php 顶部必须有一行 Route::defaultRouteClass('Route')。将其更改为Route::defaultRouteClass('InflectedRoute')
  • 此修复错误1。但错误2存在。当我输入example.com/foo/bar 时,cakephp 会查找 barController。

标签: php cakephp routing cakephp-3.0


【解决方案1】:

诸如路由元素模式之类的选项必须通过Router::connect() 的第三个参数$options 参数传递。

这条路线:

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

将捕获您的/foo/bar URL,它将匹配foo:language 元素和bar:controller 元素。基本上 URL 数组中的 language 键将被视为默认值,并且它总是会被 :language 元素值覆盖。

定义路线的正确方法是:

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

其他路线需要相应调整。

另请参阅Cookbook > Routing > Connecting Routes

【讨论】:

    【解决方案2】:

    最好的方法是使用路由范围

    <?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;
    });
    

    代码取自:

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

    【讨论】:

      【解决方案3】:

      从 CakePHP 3 应用程序框架扩展默认路由器

      原始 routes.php 已移除 cmets

      <?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);
      });
      

      用定义集中的语言修改

      <?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']]);
        

        类应用控制器 公共函数 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);
        

        }

        【讨论】:

          猜你喜欢
          • 2018-04-22
          • 2012-02-22
          • 2017-03-29
          • 2021-08-25
          • 1970-01-01
          • 2013-02-15
          • 1970-01-01
          • 2013-12-19
          • 2016-10-12
          相关资源
          最近更新 更多