Добавление префикса к каждому URL-адресу в CakePHP




cakephp textarea (3)

rchavik из IRC предложил эту ссылку: CakePHP URL-адрес переключения языков для интернационализации и локализации i18n и l10n

В общем, кажется, что решением может быть переопределение Helper::url .

Какой самый чистый способ добавить префикс для каждого URL-адреса в CakePHP, например параметр языка?

http://example.com/en/controller/action
http://example.com/ru/admin/controller/action

Он должен работать с «настоящими» префиксами, такими как admin , и в идеале голый URL /controller/action может быть перенаправлен на /DEFAULT-LANGUAGE/controller/action .

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

Таким образом, вопрос двоякий:

  • Каков наилучший способ структурирования маршрутов, поэтому параметр языка неявно включается по умолчанию без необходимости указывать для каждого вновь определенного маршрута?
    • Router::connect('/:controller/:action/*', ...) должен неявно включать префикс.
    • Параметр должен быть доступен в $this->params['lang'] или где-то аналогично оценке в AppController::beforeFilter() .
  • Как заставить Router::url() автоматически включать префикс в URL-адрес, если явно не указано?
    • Router::url(array('controller' => 'foo', 'action' => 'bar')) должен возвращать /en/foo/bar
    • Поскольку Controller::redirect() , Form::create() или даже Router::url() напрямую должны иметь одинаковое поведение, переопределение каждой отдельной функции на самом деле не является опцией. Например, Html::image() должен создавать URL без префикса.

Следующие методы, кажется, называют Router::url .

  • Controller::redirect
  • Controller::flash
  • Dispatcher::__extractParams через Object::requestAction
  • Helper::url
  • JsHelper::load_
  • JsHelper::redirect_
  • View::uuid , но только для генерации хеширования

Из них кажется, что методы Контроллера и Помощника должны быть переопределены, я мог бы жить без JsHelper . Моя идея состояла бы в том, чтобы написать общую функцию в AppController или, возможно, просто в bootstrap.php для обработки вставки параметров. Переопределенные методы Controller и Helper будут использовать эту функцию, как если бы я хотел вручную вызвать Router::url . Достаточно ли этого?


Это, по сути, весь код, который я реализовал для решения этой проблемы в конце (по крайней мере, я думаю, это все ;-)):

/config/bootstrap.php

define('DEFAULT_LANGUAGE', 'jpn');

if (!function_exists('router_url_language')) {
    function router_url_language($url) {
        if ($lang = Configure::read('Config.language')) {
            if (is_array($url)) {
                if (!isset($url['language'])) {
                    $url['language'] = $lang;
                }
                if ($url['language'] == DEFAULT_LANGUAGE) {
                    unset($url['language']);
                }
            } else if ($url == '/' && $lang !== DEFAULT_LANGUAGE) {
                $url.= $lang;
            }
        }

        return $url;
    }
}

/config/core.php

Configure::write('Config.language', 'jpn');

/app_helper.php

class AppHelper extends Helper {

    public function url($url = null, $full = false) {
        return parent::url(router_url_language($url), $full);
    }

}

/app_controller.php

class AppController extends Controller {

    public function beforeFilter() {
        if (isset($this->params['language'])) {
            Configure::write('Config.language', $this->params['language']);
        }
    }

    public function redirect($url, $status = null, $exit = true) {
        parent::redirect(router_url_language($url), $status, $exit);
    }

    public function flash($message, $url, $pause = 1) {
        parent::flash($message, router_url_language($url), $pause);
    }

}

/config/routes.php

Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/:language/', array('controller' => 'pages', 'action' => 'display', 'home'), array('language' => '[a-z]{3}'));
Router::connect('/:language/pages/*', array('controller' => 'pages', 'action' => 'display'), array('language' => '[a-z]{3}'));
Router::connect('/:language/:controller/:action/*', array(), array('language' => '[a-z]{3}'));

Это позволяет использовать URL-адреса по умолчанию, такие как /controller/action использовать язык по умолчанию (JPN в моем случае) и URL-адреса, такие как /eng/controller/action чтобы использовать альтернативный язык. Эта логика может быть легко изменена в функции router_url_language() .

Для этого мне также нужно определить два маршрута для каждого маршрута, один из которых содержит /:language/ параметр, а другой - без. По крайней мере, я не мог понять, как это сделать по-другому.


Более простой способ - сохранить выбранный язык в файле cookie, а затем не переписывать все URL-адреса. Вы также можете автоматически определить язык браузера пользователя.

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

Но любите полное решение, которое вы публикуете, очень всеобъемлющее, спасибо. :-)





prefix