2009-11-25 33 views
20

Cách sạch nhất để thêm tiền tố vào mọi URL trong CakePHP, như thông số ngôn ngữ là gì?Thêm tiền tố vào mỗi URL trong CakePHP

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

Nó cần phải làm việc với tiền tố "thật" như admin, và lý tưởng URL trần /controller/action có thể được chuyển hướng đến /DEFAULT-LANGUAGE/controller/action.

Nó đang hoạt động trong ứng dụng được trang bị retro cho tôi, nhưng đó là loại hack và tôi cần bao gồm tham số ngôn ngữ bằng tay trong hầu hết các liên kết, điều này không tốt.

Vậy câu hỏi gồm hai phần:

  • cách tốt nhất để cấu trúc đường là gì, vì vậy tham số ngôn ngữ được ngầm bao gồm theo mặc định mà không cần phải được xác định cho từng Route mới được xác định?
    • Router::connect('/:controller/:action/*', ...) hoàn toàn nên bao gồm tiền tố.
    • Tham số phải có sẵn trong $this->params['lang'] hoặc một nơi nào đó tương tự được đánh giá trong AppController::beforeFilter().
  • Cách nhận Router::url() để tự động bao gồm tiền tố trong URL, nếu không được chỉ định rõ ràng?
    • Router::url(array('controller' => 'foo', 'action' => 'bar')) nên trở /en/foo/bar
    • Kể từ Controller::redirect(), Form::create() hoặc thậm chí Router::url() trực tiếp cần phải có hành vi tương tự, trọng mỗi chức năng duy nhất là không thực sự là một lựa chọn. Ví dụ: Html::image() sẽ tạo ra một URL ít tiền tố hơn.

Các phương pháp sau đây dường như gọi Router::url.

  • Controller::redirect
  • Controller::flash
  • Dispatcher::__extractParams qua Object::requestAction
  • Helper::url
  • JsHelper::load_
  • JsHelper::redirect_
  • View::uuid, nhưng chỉ cho một thế hệ băm

Trong số đó có vẻ như các phương thức Bộ điều khiển và Trình trợ giúp cần được ghi đè, tôi có thể sống mà không có JsHelper. Ý tưởng của tôi là viết một hàm tổng quát trong AppController hoặc có thể chỉ trong bootstrap.php để xử lý chèn tham số. Các phương thức Bộ điều khiển và Trình trợ giúp bị ghi đè sẽ sử dụng hàm này, như tôi sẽ làm nếu tôi muốn gọi thủ công Router::url. Điều này có đủ không?

Trả lời

14

Đây là về cơ bản tất cả các mã tôi thực hiện để giải quyết vấn đề này cuối cùng (ít nhất tôi nghĩ rằng đó là tất cả ;-)):

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

Điều này cho phép các URL mặc định như /controller/action sử dụng ngôn ngữ mặc định (JPN trong trường hợp của tôi) và các URL như /eng/controller/action để sử dụng lựa chọn thay thế ngôn ngữ ative. Logic này có thể được thay đổi khá dễ dàng trong hàm router_url_language().

Để làm việc này, tôi cũng cần xác định hai tuyến cho mỗi tuyến, một tuyến chứa thông số /:language/ và một không có. Ít nhất tôi không thể tìm ra cách làm theo cách khác.

+0

Câu trả lời hay, điều này thực sự đã giúp tôi. – gacrux

+2

@gacrux Lưu ý rằng điều này sẽ ít phức tạp hơn trong Bánh 1.3, bao gồm các tiền tố tùy chỉnh. Những điều trên áp dụng cho Bánh 1.2, chỉ biết * tiền tố * một. :) – deceze

0

Cách dễ dàng hơn là lưu trữ ngôn ngữ đã chọn trong cookie và sau đó không phải viết lại tất cả các URL. Bạn cũng có thể tự động phát hiện ngôn ngữ trình duyệt của người dùng.

Tuy nhiên, công cụ tìm kiếm sẽ không thể nhận nhiều ngôn ngữ khác nhau và bạn cũng sẽ mất ngôn ngữ nếu ai đó cố chia sẻ liên kết.

Nhưng yêu thích giải pháp đầy đủ mà bạn đã đăng, rất toàn diện, cảm ơn. :-)

+1

Sự cố với công tắc ngôn ngữ "URL ít" là công cụ tìm kiếm. Họ sẽ chỉ bao giờ lập chỉ mục một ngôn ngữ hoặc sẽ nhận được quần lót của họ trong một nhóm nếu họ thấy nội dung khác nhau trên cùng một URL. Điều đó chỉ thực sự hoạt động cho các khu vực riêng tư (chỉ dành cho đăng nhập) của trang web của bạn. – deceze

+0

Ồ, đó là một điểm tốt. Tôi sẽ cập nhật câu trả lời của tôi để lưu ý rằng. –

Các vấn đề liên quan