Префикс языка CakePHP 2.x в правилах маршрутизации не применяется, когда пользователь запрашивает отсутствующий контроллер

По-моему, немного непонятный вопрос. Я успешно настроил префикс языка для всех моих правил маршрутизации для обработки локализации. Все отлично работает, когда пользователь запрашивает контроллеры, которые существуют в приложении (например, /users/view/4). В моем AppController приложение успешно перенаправляет любые запросы, в которых отсутствует языковой префикс, на URL-адрес, у которого он есть (например, /eng/users/view/4).

Проблема возникает, когда пользователь запрашивает неверный контроллер. В этом случае после перенаправления пользователя приложение выдает исключение MissingControllerException (которое должно быть), но контроллер, о котором оно сообщает как недействительный, является самим языковым префиксом (например, «EngController»), а не контроллером, который идет после этого в URI запроса. .

Это указывает на то, что в состоянии ошибки приложение Cake больше не знает о маршрутизации языковых префиксов. Это говорит о том, что мне нужно добавить еще одно правило маршрутизации в route.php, которое будет нацелено только на недопустимые запросы и гарантирует, что префикс языка ожидается и учитывается во всех запросах, которые обрабатываются CakeErrorController (который является основным контроллером, который берет на себя эти типы). исключений).

Но я просмотрел документы и понятия не имею, как создать такой маршрут. Спасибо за вашу помощь!

Вот мой файл route.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';

person Adam Friedman    schedule 23.08.2019    source источник
comment
Не могли бы вы обновить свой вопрос с помощью файла route.php?   -  person Coreus    schedule 25.08.2019


Ответы (1)


Изменить. Обновите маршрутизатор, чтобы он использовал отрицательный прогноз для языков, поддерживаемых вашим приложением.

Вот пример регулярного выражения:

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

Любой маршрут, который не начинается с spa, eng или swe, вы должны перенаправить на контроллер и действие по вашему выбору.

В вашем маршрутизаторе

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

Вам понадобится этот шаблон маршрута для каждого раздела, так как количество параметров URL-адреса варьируется.

Вы можете протестировать регулярное выражение с помощью различных онлайн-инструментов Regex. Вот шаблон с тестовыми данными, чтобы убедиться, что он работает.


Исходное сообщение:

Возможно, вы слишком много думаете об этом.

Ваш вопрос о том, как добавить маршрут для MissingController, что происходит только при разработке (в режиме отладки). В производстве это превращается в 404.

Поскольку показать разработчику, чего не хватает, — это то, что должен делать любой правильный фреймворк (включая CakePHP), вам не следует браться за написание собственного ExceptionHandler для этих случаев, чтобы попытаться впихнуть какое-то причудливое решение.

Вместо этого вам следует обратить внимание на обработку этого 404, поскольку, как уже говорилось, после запуска в производство это сообщение об ошибке по умолчанию будет отображаться как сообщение об ошибке 404.

Вот как выглядит тот же (отсутствующий) маршрут:

В режиме разработки:

введите здесь описание изображения

В производственном режиме:

введите здесь описание изображения

Обработка 404

Если вы хотите отобразить 404, этот вопрос объясняет, как настроить эту страницу ошибки.

Если вы хотите перенаправить куда-либо, когда происходит ошибка 404, вы можете сделать что-то вроде этого (из этого вопроса):

Чтобы перехватывать и обрабатывать ошибки 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.
    }

Надеюсь, что-то из этого имело смысл.

person Coreus    schedule 26.08.2019
comment
Спасибо за Ваш ответ. Я очень конкретно спрашиваю об исправлении ошибки режима отладки, чтобы иметь ошибки, которые не вводят в заблуждение меня и других разработчиков, работающих над приложением. (Я хорошо знаю, что это 404-е в производстве.) У меня есть ощущение, что я мог бы добавить одну строчку к маршрутам, чтобы исправить это. Я бы предпочел не реорганизовывать свою парадигму маршрутизации. - person Adam Friedman; 27.08.2019
comment
Первоначально в ответе была часть, касающаяся написания пользовательских обработчиков исключений для MissingControllerExceptions, но идея настолько ужасна, что я удалил ее. О том, как создавать собственные обработчики исключений, можно прочитать здесь: book.cakephp.org/2.0/en/development/ - person Coreus; 28.08.2019
comment
@AdamFriedman В ответе теперь есть обновленное предложение. Посмотрите на это, и если это помогло вам, пожалуйста, примите ответ. - person Coreus; 28.08.2019