【问题标题】:CakePHP 2.x language prefix in routing rules are not being applied when user requests a missing controller当用户请求缺少控制器时,不会应用路由规则中的 CakePHP 2.x 语言前缀
【发布时间】:2019-08-23 17:30:25
【问题描述】:

我认为这是一个晦涩难懂的问题。我已经成功地为我的所有路由规则设置了语言前缀来处理本地化。当用户请求应用程序中存在的控制器时,一切都很好(例如,/users/view/4)。在我的 AppController 中,我让应用程序成功地将任何缺少语言前缀的请求重定向到具有语言前缀的 URL(例如,/eng/users/view/4)。

当用户请求无效的控制器时,就会出现问题。在这种情况下,在重定向用户之后,应用程序会抛出 MissingControllerException(它应该),但它报告为无效的控制器是语言前缀本身(例如,“EngController”),而不是请求 URI 中此之后的控制器.

这表明在错误状态下,Cake 应用程序不再知道任何语言前缀路由。这表明我需要向 routes.php 添加另一个路由规则,该规则将仅针对无效请求,并确保在 CakeErrorController 处理的任何请求中都需要语言前缀(这是接管这些类型的核心控制器)例外)。

但是我已经搜索了文档,但我不知道如何制作这样的路线。感谢您的帮助!

这是我的 routes.php 文件:

<?php


$lang_settings = ['language' => '[a-z]{3}'];

// ElStats homepage vs tenant homepage
if(!TENANT) {
    Router::connect('/', ['controller' => 'pages', 'action' => 'index'], $lang_settings);
    Router::connect('/:language', ['controller' => 'pages', 'action' => 'index'], $lang_settings);
} else {
    Router::connect('/', ['controller' => 'pages', 'action' => 'index'], $lang_settings);
    Router::connect('/:language', ['controller' => 'pages', 'action' => 'index'], $lang_settings);
}


/**
 * ...and connect the rest of 'Pages' controller's urls.
 */

Router::connect('/:language/pages/*', ['controller' => 'pages', 'action' => 'display'], $lang_settings);
Router::connect('/:language/contests/search/*', ['controller' => 'contests', 'action' => 'index'], $lang_settings);
Router::connect('/:language/contests/:action/*', ['controller'=>'contests'], $lang_settings);
Router::connect('/:language/contests/*', ['controller' => 'contests', 'action' => 'index'], $lang_settings);
Router::connect('/:language/candidates/search/*', ['controller' => 'candidates', 'action' => 'index'], $lang_settings);
Router::connect('/:language/candidates/:action/*', ['controller'=>'candidates'], $lang_settings);
Router::connect('/:language/candidates/*', ['controller' => 'candidates', 'action' => 'index'], $lang_settings);

// If just /search, then default to /contests/search
Router::connect('/:language/search/*', ['controller' => 'contests', 'action' => 'index'], $lang_settings);

/**
 * Full-controller alias routing
 */

// ballot_questions => contests
Router::connect('/:language/ballot_questions/search/*', ['controller' => 'contests', 'action' => 'index'], $lang_settings);
Router::connect('/:language/ballot_questions/:action/*', ['controller'=>'contests'], $lang_settings);
Router::connect('/:language/ballot_questions/*', ['controller'=>'contests', 'action' => 'index'], $lang_settings);
Router::connect('/:language/admin/ballot_questions/:action/*', ['controller'=>'contests','admin' => true], $lang_settings);
Router::connect('/:language/admin/ballot_questions/*', ['controller'=>'contests', 'action' => 'index', 'admin' => true], $lang_settings);

// Admin Routing
Router::connect('/:language/admin', [ 'controller'=> 'pages', 'action'=> 'index','admin' => true], $lang_settings);
Router::connect('/:language/admin/:controller/:action/*',['admin' => true], $lang_settings);
Router::connect('/:language/admin/:controller/*',['admin' => true], $lang_settings);
Router::connect('/:language/:controller/:action/*',[], $lang_settings);

require CAKE . 'Config' . DS . 'routes.php';

【问题讨论】:

  • 你能用你的 routes.php 文件更新你的问题吗?

标签: php exception cakephp routing cakephp-2.x


【解决方案1】:

编辑:更新您的路由器以对您的应用程序支持的语言使用负前瞻。

这是一个正则表达式示例:

^(?!(spa|eng|swe)){1}.*

任何不以 spaeng​​strong> 或 swe 开头的路线,您都会将其重定向到您的控制器和操作选择。

在您的路由器中

Router::connect(
    '/:language/candidates/search/*',
    array('controller' => 'errorController', 'action' => 'index'),
    array('language' => '^(?!(spa|eng|swe)).*')
);

每个部分都需要这种路由模式,因为 url 参数的数量会有所不同。

您可以使用各种在线正则表达式工具测试正则表达式。 Here's that pattern with some test data 验证它是否有效。


原帖:

你可能想多了。

您的问题是关于如何为 MissingController 添加路由,这只会在您开发时(在调试模式下)发生。在生产中,这变成了 404。

既然向开发人员展示了任何适当的框架应该做的事情(包括 CakePHP),你不应该着手为这些情况编写自己的 ExceptionHandler 来尝试硬塞一些奇怪的解决方案。

相反,您应该考虑处理该 404,因为如前所述,一旦投入生产,该错误消息将默认为 404 错误消息。

以下是相同(缺失)路线的外观:

在开发模式下:

在生产模式下:

处理 404

如果您想显示 404,this question 解释了如何自定义此错误页面。

如果您想在 404 发生时重定向某个地方,您可以执行以下操作 (from this question):

要捕获和处理 404 错误,您需要扩展 ErrorHandler 类并覆盖error404方法。为此,请创建文件 app/app_error.php 代码如下:

class AppError extends ErrorHandler {
    function error404($params) {
        // redirect to homepage (or any page you like)
        $this->controller->redirect('/');
    }
}

一些旁注

为了让您自己更轻松,请考虑更改您的路由方案以将语言作为请求参数包含在内。否则搜索引擎(如果您的网站应该是索引)将抓取您的语言页面,而这并不总是您想要的。

这意味着你会有这样的路线:

candidates/list?lang=eng

这样,您可以通过以下方式更轻松地处理无效语言代码:

    // In a controller
    $languageCode = $this->request->params['lang'];
    if (!in_array($language, ['eng', 'spa', 'swe'])) {
      // Set a variable to view to display a wrong error code, or redirect to a default language.
    }

希望这一切都有意义。

【讨论】:

  • 感谢您的回答。我非常特别地询问修复调试模式错误,以便出现不会误导我和其他开发应用程序的开发人员的错误。 (我很清楚这些是生产中的 404。)我有一种感觉,我可以在路线中添加一条单线来解决这个问题。我宁愿不重构我的路由范式。
  • 答案最初有一部分是关于为 MissingControllerExceptions 编写自定义异常处理程序,但这个想法太可怕了,我把它删除了。您可以在此处阅读如何制作自己的异常处理程序:book.cakephp.org/2.0/en/development/…
  • @AdamFriedman 答案现在有一个更新的建议。看看那个,如果对你有帮助,请接受答案。
猜你喜欢
  • 2014-02-06
  • 1970-01-01
  • 2011-01-03
  • 2012-12-27
  • 1970-01-01
  • 2017-05-12
  • 1970-01-01
  • 2011-06-09
相关资源
最近更新 更多