2011-03-01 88 views
8

我正在用Zend開發一個Rest控制器,並且我將URL與URL的映射混淆了。在Zend Framework中使用Zend_Controller_Router_Route_Regex在參數中匹配多個URL

基本上我讀了約Zend Router,我無法計劃我的網址,以滿足上述路線。

這些是我應該映射到路由器的一些URL。

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

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

  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(params :123456,pings.xml,A = 1,B = 2)

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

我打算使得對於鏈接模式1〜 3,「標籤」應該是控制器,對於url模式4到6,「ping」應該是控制器。

現在我不確定如何配置路由器,以便上述方案可以工作。 請注意,我無法更改這些網址。我可以提供100個我的聲望分數給好的答案。

+1

我可以爲您投票 – 2011-03-01 09:27:26

+0

爲什麼在所有這些網址的開頭都有/需要「public/index.php」? – 2011-03-01 10:04:41

+0

他們不是強制性的,我刪除它們。我只是擔心這些網址路由到他們各自的控制器和操作,傳遞所需的參數。 – 2011-03-01 12:14:26

回答

6

前兩個URL可以合併到一個路由器。

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

要區分前兩條路線,請檢查標記控制器中是否存在abc參數。在您的標籤控制器索引操作中添加以下內容。

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

類似地,路線4和5可以組合成一條路線。

我已經解釋過路由6.對於路由3,您可以使用相同的邏輯。

$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); 

這些參數可以在ping控制器中像下面一樣訪問。

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

對於路線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); 

的參數(?後的URL的一部分)將不會在路由器中處理。默認情況下,它們將被傳遞給你的控制器。

要獲得URL中傳遞的特定參數值,請在控制器中使用以下內容。

$this->_getParam('a'); 

的邏輯是使用(。*)在你的路線,併爲它們分配一個參數名稱和您的控制器訪問它們

+0

@emaillenin謝謝,這工作完美,但我無法得到第五種情況下的正則表達式格式。你能爲此發表一個例子嗎?我無法獲得參數a = 1和b = 2。 – 2011-03-01 15:11:43

+0

@dskanth pings.xml是URL的靜態部分? – emaillenin 2011-03-01 16:59:17

+0

對不起,遲到了,但是,pings.xml是第5個網址的靜態部分,我希望之後的部分。 – 2011-03-02 04:53:49

4

下面是一塊算法是提煉控制器,索引PARAMS首發,從請求,這你可以納入的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; 
} 

它幾乎沒有進行測試,當然因此不生產材料。但它應該讓你開始。

這裏做的事情讓你至今:
控制器
擴展
的索引參數

什麼這不會給你的是:
的操作(POST,PUT,刪除等。這個算法已經在Zend_Rest_Route::match()
命名參數(Zend_Controller_Request_Http需要的是護理的話)

編輯
我知道這個答案可能被認爲有點模糊。重點是將此算法與Zend_Rest_Routematch()算法合併。但是,上面的代碼仍然需要很多關注;你也可能會考慮模塊(如Zend_Rest_Route),甚至可能還有一個可選的baseUrl(不確定ZF如何在內部處理這個問題)。