代码之家  ›  专栏  ›  技术社区  ›  deceze

为cakephp中的每个URL添加前缀

  •  20
  • deceze  · 技术社区  · 15 年前

    向cakephp中的每个URL添加前缀(比如语言参数)最干净的方法是什么?

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

    它需要使用“real”前缀,比如 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() 甚至 路由器::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 处理参数插入。重写的控制器和助手方法将使用此函数,如果我想手动调用 路由器:网址 . 这就足够了吗?

    3 回复  |  直到 12 年前
        1
  •  5
  •   Joe Phillips    15 年前

    IRC的Rchavik建议此链接: CakePHP URL based language switching for i18n and l10n internationalization and localization

    一般来说,似乎 Helper::url 可能是解决办法。

        2
  •  14
  •   deceze    14 年前

    这基本上就是我最终解决这个问题所实现的所有代码(至少我认为这就是全部;-):

    /配置/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');
    

    /AppHelPiel.PHP

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

    /应用程序控制器.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);
        }
    
    }
    

    /配置/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/ 参数和一个没有。至少我不知道该怎么做。

        3
  •  0
  •   Simon E. pbs    12 年前

    一种更简单的方法是将所选语言存储在cookie中,然后不必重写所有的URL。您还可以自动检测用户的浏览器语言。

    然而 ,搜索引擎不太可能获取各种语言,如果有人试图共享链接,您也会丢失语言。

    但是喜欢你发布的完整解决方案,非常全面,谢谢。-)