2011-09-27 41 views
2

我有一個小問題,我的國際化:CakePHP的:基於URL的國際

我希望有一些URL看起來像這樣:http://mywebsite/eng/controller/action/params ...

我發現這個http://nuts-and-bolts-of-cakephp.com/2008/11/28/cakephp-url-based-language-switching-for-i18n-and-l10n-internationalization-and-localization/

這是大部分時間工作都很好。但我有一個情況,這不是預期的結果。

當我使用$這個 - > HTML的「鏈接與命名參數,我沒有得到我的漂亮的結構,但類似http://mywebsite/controller/action/paramX:aaa/paramxY:bbb/language:eng

我覺得這是一個路由的問題,但我可以」不知道怎麼回事?

非常感謝您

回答

0

我終於做了這個定義該航線: 我創建了一個自定義CakeRoute,在這個cakeRoute中,我重寫了「match」url和_writeUrl方法。

現在,每一件事情是工作就像一個魅力:)

對於那些由路由類interessted:

<?php 
class I18nRoute extends CakeRoute { 
/** 
* Constructor for a Route 
* Add a regex condition on the lang param to be sure it matches the available langs 
* 
* @param string $template Template string with parameter placeholders 
* @param array $defaults Array of defaults for the route. 
* @param string $params Array of parameters and additional options for the Route 
* @return void 
* @access public 
*/ 
    public function __construct($template, $defaults = array(), $options = array()) { 
     //$defaults['language'] = Configure::read('Config.language'); 
     $options = array_merge((array)$options, array(
      'language' => join('|', Configure::read('Config.languages')) 
     )); 
     parent::__construct($template, $defaults, $options); 
    } 

/** 
* Attempt to match a url array. If the url matches the route parameters + settings, then 
* return a generated string url. If the url doesn't match the route parameters false will be returned. 
* This method handles the reverse routing or conversion of url arrays into string urls. 
* 
* @param array $url An array of parameters to check matching with. 
* @return mixed Either a string url for the parameters if they match or false. 
* @access public 
*/ 
    public function match($url) { 
     if (empty($url['language'])) { 
      $url['language'] = Configure::read('Config.language'); 
     } 

     if (!$this->compiled()) { 
      $this->compile(); 
     } 
     $defaults = $this->defaults; 

     if (isset($defaults['prefix'])) { 
      $url['prefix'] = $defaults['prefix']; 
     } 

     //check that all the key names are in the url 
     $keyNames = array_flip($this->keys); 
     if (array_intersect_key($keyNames, $url) != $keyNames) { 
      return false; 
     } 

     $diffUnfiltered = Set::diff($url, $defaults); 
     $diff = array(); 

     foreach ($diffUnfiltered as $key => $var) { 
      if ($var === 0 || $var === '0' || !empty($var)) { 
       $diff[$key] = $var; 
      } 
     } 

     //if a not a greedy route, no extra params are allowed. 
     if (!$this->_greedy && array_diff_key($diff, $keyNames) != array()) { 
      return false; 
     } 

     //remove defaults that are also keys. They can cause match failures 
     foreach ($this->keys as $key) { 
      unset($defaults[$key]); 
     } 
     $filteredDefaults = array_filter($defaults); 

     //if the difference between the url diff and defaults contains keys from defaults its not a match 
     if (array_intersect_key($filteredDefaults, $diffUnfiltered) !== array()) { 
      return false; 
     } 

     $passedArgsAndParams = array_diff_key($diff, $filteredDefaults, $keyNames); 
     list($named, $params) = Router::getNamedElements($passedArgsAndParams, $url['controller'], $url['action']); 

     //remove any pass params, they have numeric indexes, skip any params that are in the defaults 
     $pass = array(); 
     $i = 0; 
     while (isset($url[$i])) { 
      if (!isset($diff[$i])) { 
       $i++; 
       continue; 
      } 
      $pass[] = $url[$i]; 
      unset($url[$i], $params[$i]); 
      $i++; 
     } 
/* 
     //still some left over parameters that weren't named or passed args, bail. 
     //We don't want this behavior, we use most of args for the matching, and if we have more, we just allow them as parameters 
     if (!empty($params)) { 
      return false; 
     }*/ 

     //check patterns for routed params 
     if (!empty($this->options)) { 
      foreach ($this->options as $key => $pattern) { 
       if (array_key_exists($key, $url) && !preg_match('#^' . $pattern . '$#', $url[$key])) { 
        return false; 
       } 
      } 
     } 
     return $this->_writeUrl(array_merge($url, compact('pass', 'named'))); 
    } 

    function _writeUrl($params) { 
     if (isset($params['prefix'], $params['action'])) { 
      $params['action'] = str_replace($params['prefix'] . '_', '', $params['action']); 
      unset($params['prefix']); 
     } 

     if (is_array($params['pass'])) { 
      $params['pass'] = implode('/', $params['pass']); 
     } 

     $instance =& Router::getInstance(); 
     $separator = $instance->named['separator']; 

     if (!empty($params['named']) && is_array($params['named'])) { 
      $named = array(); 
      foreach ($params['named'] as $key => $value) { 
       $named[] = $key . $separator . $value; 
      } 
      $params['pass'] = $params['pass'] . '/' . implode('/', $named); 
     } 
     $out = $this->template; 

     $search = $replace = array(); 
     foreach ($this->keys as $key) { 
      $string = null; 
      if (isset($params[$key])) { 
       $string = $params[$key]; 
      } elseif (strpos($out, $key) != strlen($out) - strlen($key)) { 
       $key .= '/'; 
      } 
      $search[] = ':' . $key; 
      $replace[] = $string; 
     } 
     $out = str_replace($search, $replace, $out); 

     if (strpos($this->template, '*')) { 
      $out = str_replace('*', $params['pass'], $out); 
     } 
     $out = str_replace('//', '/', $out); 
     //Modified part: allows us to print unused parameters 
     foreach($params as $key => $value){ 
      $found = false; 
      foreach($replace as $repValue){ 
       if($value==$repValue){ 
        $found=true; 
        break; 
       } 
      } 
      if(!$found && !empty($value)){ 
       $out.="/$key:$value"; 
      } 
     } 
     return $out; 
    } 
} 

,你可以設置這樣的路線:

Router::connect('/:language/:controller/*', array(), array('routeClass' => 'I18nRoute')); 
0

這是因爲CakePHP的好好嘗試一下找到routes.php文件的路由對應這個鏈接。換句話說,你必須在routes.php文件文件

Router::connect('/:language/:controller/:action/:paramX/:paramY'); 

一旦這一套,這 - $> HTML的「鏈接將輸出一個不錯的URL

+0

我只是不能聲明所有的參數,我使用的是命名參數,因爲我有很多參數,大部分時候它們都沒有被填充,所以它給了我一個指數級的組合。(我有這個大多數情況下我的c ontrollers) 而我有一個*在我的控制器聲明後,爲什麼這不起作用? 我在想,如果cakePhp能夠捕獲像/:controller /:action/*這樣的url,它應該能夠匹配像/:language /:controller /:action/*這樣的url。 – J4N