2011-03-01 8 views
8

tôi đang phát triển Bộ điều khiển còn lại với Zend và tôi bị nhầm lẫn với ánh xạ các url tới Bộ định tuyến.Kết hợp nhiều URL với các tham số bằng cách sử dụng Zend_Controller_Router_Route_Regex trong Zend Framework

Về cơ bản tôi đã đọc về Zend Router và tôi không thể lên kế hoạch cho các url của mình để đáp ứng các tuyến đường đã đề cập.

Đây là một số url của tôi nên được ánh xạ tới Bộ định tuyến.

  1. http://localhost/api/v1/tags.xml

  2. http://localhost/api/v1/tags.xml?abc=true (param: abc = true)

  3. http://localhost/api/v1/tags/123456.xml (param: 123456.xml)

  4. http://localhost/api/v1/tags/123456/pings.xml (params: 123456, pings.xml)

  5. http://localhost/api/v1/tags/123456/pings.xml?a=1&b=2 (thông số : 123456, pings.xml, a = 1, b = 2)

  6. http://localhost/api/v1/tags/123456/pings/count.xml (params: 123456, ping, count.xml)

Tôi đang lên kế hoạch như vậy mà cho các mẫu url 1 tới 3, "thẻ" nên là bộ điều khiển và cho các mẫu url 4 đến 6, "ping" phải là bộ điều khiển.

Bây giờ tôi không chắc về cách định cấu hình các bộ định tuyến sao cho các tình huống trên sẽ hoạt động. Lưu ý rằng tôi không thể thay đổi các url này. Tôi có thể cung cấp 100 điểm danh tiếng của tôi cho câu trả lời hay.

+1

tôi có thể bỏ phiếu cho bạn –

+0

Tại sao bạn có/cần "public/index.php" ở đầu tất cả các URL này? –

+0

Chúng không bắt buộc và tôi đã xóa chúng. Tôi chỉ lo lắng về việc định tuyến các url này đến các bộ điều khiển và hành động tương ứng của chúng, chuyển các tham số cần thiết. –

Trả lời

6

Hai URL đầu tiên có thể được kết hợp với một bộ định tuyến.

$r = new Zend_Controller_Router_Route_Regex('api/v1/tags.xml', 
       array('controller' => 'tags', 'action' => 'index')); 
$router->addRoute('route1', $r); 

Để phân biệt hai tuyến đầu tiên, hãy kiểm tra sự hiện diện của tham số abc trong bộ điều khiển thẻ của bạn. Thêm thông tin sau vào bộ điều khiển thẻ, tác vụ chỉ mục của bạn.

if($this->_getParam('abc') == "true") 
{ 
//route 2 
} else { 
// route 1 
} 

Tương tự, các tuyến 4 và 5 có thể được kết hợp thành một tuyến đường.

Tôi đã giải thích cho Tuyến đường 6. Đối với tuyến đường 3, bạn có thể sử dụng cùng một logic.

$r = new Zend_Controller_Router_Route_Regex('api/v1/tags/(.*)/pings/(.*)', 
       array('controller' => 'pings', 'action' => 'index'), 
array(1 => 'param1',2=>'param2') 
); 
$router->addRoute('route6', $r); 

Các thông số sau đó có thể được truy cập như sau trong bộ điều khiển Ping.

$this->_getParam('param1') and $this->_getParam('param2') 

Đối Route 5:

$r = new Zend_Controller_Router_Route_Regex('api/v1/tags/(.*)/pings.xml', 
       array('controller' => 'pings', 'action' => 'index'), 
array(1 => 'param1') 
); 
$router->addRoute('route5', $r); 

Các thông số (? Một phần của URL sau) sẽ không được xử lý trong Router. Theo mặc định, chúng sẽ được chuyển tới bộ điều khiển của bạn.

Để nhận giá trị thông số specifc được truyền trong URL của bạn, hãy sử dụng thông tin sau trong bộ điều khiển của bạn.

$this->_getParam('a'); 

Logic là sử dụng (. *) Trong lộ trình của bạn và gán cho họ một tên tham số và truy cập chúng trong điều khiển của bạn

+0

@emaillenin Cảm ơn, đã hoạt động hoàn hảo, nhưng tôi không thể lấy định dạng regex cho trường hợp thứ 5. Bạn có thể xin một ví dụ cho điều đó không? Tôi không thể lấy các tham số a = 1 & b = 2. –

+0

@dskanth pings.xml là một phần tĩnh của URL? – emaillenin

+0

Xin lỗi vì đã trễ, nhưng có, pings.xml là phần tĩnh của url thứ 5, tôi muốn phần sau đó. –

4

Dưới đây là một khởi đầu cho một mảnh của thuật toán mà distills bộ điều khiển, params lập chỉ mục, và mở rộng từ yêu cầu, mà bạn có thể kết hợp thành một phiên bản mở rộng của Zend_Rest_Route::match():

public function match($request) 
{ 
    $path = $request->getPathInfo(); 

    // distill extension (if any) and the remaining path 
    preg_match('~(?U:(?<path>.*))(?:\.(?<extension>[^\.]*))?$~', $path, $matches); 
    $this->_values[ '_extension' ] = isset($matches[ 'extension' ]) ? $matches[ 'extension' ] : null; 
    $path = isset($matches[ 'path' ]) ? $matches[ 'path' ] : ''; 

    // split the path into segments 
    $pathSegments = preg_split('~' . self::URI_DELIMITER . '~', $path, -1, PREG_SPLIT_NO_EMPTY); 

    // leave if no path segments found? up to you to decide, but I put it in anyway 
    if(0 == ($length = count($pathSegments))) 
    { 
     return false; 
    } 

    // initialize some vars 
    $params = array(); 
    $controller = null; 

    // start finding the controller 
    // (presumes controller found at segment 0, 2, 4, etc...) 
    for($i = 0; $i < $length; $i += 2) 
    { 
     // you should probably check here if this is a valid REST controller 
     // (see Zend_Rest_Route::_checkRestfulController()) 
     $controller = $params[] = $pathSegments[ $i ]; 
     if(isset($pathSegments[ $i + 1 ])) 
     { 
      $params[] = $pathSegments[ $i + 1 ]; 
     } 
    } 
    // remove the param which is the actual controller 
    array_splice($params, $i - 2, 1); 

    // set the controller 
    $this->_values[ 'controller' ] = $controller; 

    // merge the params and defaults 
    $this->_values = array_merge($this->_values, $params, $this->_defaults); 

    return $this->_values; 
} 

Nó hầu như không được kiểm tra, và do đó không nguyên liệu sản xuất nhiên. Nhưng nó sẽ giúp bạn bắt đầu.

Điều này không cung cấp cho bạn cho đến nay là:
Bộ điều khiển
Việc gia hạn
Các thông số được lập chỉ mục

Điều này KHÔNG cung cấp cho bạn là:
Hành động (bưu điện, đặt, xóa, vv . các thuật toán cho điều này là đã có trong Zend_Rest_Route::match())
các thông số được đặt tên (Zend_Controller_Request_Http chăm sóc đó đã được)

EDIT
Tôi nhận ra câu trả lời này có thể được coi là hơi mơ hồ cho đến nay. Vấn đề là hợp nhất thuật toán này với thuật toán match() của Zend_Rest_Route. Nhưng mã trên vẫn cần rất nhiều sự chú ý; bạn muốn tính đến các mô-đun quá có thể (cũng như Zend_Rest_Route), và thậm chí có thể là một baseUrl tùy chọn (không chắc chắn cách mà ZF giao dịch với nội bộ này thực sự).