2011-03-01 19 views
8

Zajmuję się tworzeniem kontrolera dostępu za pomocą Zend i jestem mylony z mapowaniem adresów URL do routera.Dopasowywanie wielu adresów URL z parametrami za pomocą Zend_Controller_Router_Route_Regex w Zend Framework

Zasadniczo czytałem o numerze Zend Router i nie mogłem zaplanować adresów URL w celu zaspokojenia wymienionych tras.

Oto niektóre z moich adresów URL, które należy zmapować na Routery.

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

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

  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 (parametry : 123456, pings.xml, a = 1, b = 2)

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

ja planowania, tak że na 1 do wzorców URL 3, "tagi" powinny być kontrolerem, a dla wzorców adresów URL od 4 do 6, "pingi" powinny być kontrolerem.

Nie mam pewności, jak skonfigurować routery, aby powyższe scenariusze działały. Pamiętaj, że nie mogę zmienić tych adresów URL. Mogę zaoferować 100 punktów reputacji do dobrej odpowiedzi.

+1

Mogę zagłosować na ciebie –

+0

Dlaczego masz/potrzebujesz "public/index.php" na początku wszystkich tych adresów? –

+0

Nie są one obowiązkowe i usunąłem je. Martwię się tylko o routing tych adresów do ich kontrolerów i działań, przekazując potrzebne parametry. –

Odpowiedz

6

Pierwsze dwa adresy URL można połączyć w jeden router.

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

Aby rozróżnić pierwsze dwie trasy, sprawdź obecność parametru abc w kontrolce znaczników. Dodaj następujące elementy do kontrolera znaczników, akcji indeksowania.

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

Podobnie, trasy 4 i 5 można łączyć w jedną trasę.

Wyjaśniłem dla trasy 6. W przypadku trasy 3 można użyć tej samej logiki.

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

Parametry można wówczas uzyskać w następujący sposób w kontrolerach pingi.

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

dla trasy 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); 

parametry (? Część zawartości po), nie będą obsługiwane w routerze. Domyślnie będą przekazywane do kontrolera.

Aby uzyskać określoną wartość parametru przekazywaną w adresie URL, użyj w kontrolerze następujących elementów.

$this->_getParam('a'); 

Logika jest zastosowanie (. *) W trasie i przypisz im nazwę parametru, a dostęp do nich w swoim kontrolerze

+0

@emaillenin Dzięki, że działało idealnie, ale nie mogłem uzyskać formatu regex dla 5. przypadku. Czy możesz podać przykład tego? Nie mogłem uzyskać parametrów a = 1 i b = 2. –

+0

@dskanth pings.xml jest statyczną częścią adresu URL? – emaillenin

+0

Przepraszamy za spóźnienie, ale tak, pings.xml jest statyczną częścią piątego adresu URL, chcę część po tym. –

4

Oto rozrusznik o kawałek algorytm, który destyluje sterownika, indeksowane params, i rozszerzenie z wniosku, który można było naniesienie w rozszerzonej wersji 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; 
} 

To ledwie przetestowany, a tym samym nie materiał produkcja oczywiście. Ale powinno zacząć.

Co to daje tak daleko jest:
Kontroler
Rozszerzenie
Indeksowane parametry

Co nie daje to:
Akcja (poczta, mówiąc, usuwanie, etc . algorytm ten jest już w Zend_Rest_Route::match())
nazwanych parametrów (Zend_Controller_Request_Http dba o to już)

EDYCJA Zdaję sobie sprawę, że tę odpowiedź można uznać za mało ogólnikową. Chodzi o scalenie tego algorytmu z algorytmem match() z Zend_Rest_Route. Ale powyższy kod nadal wymaga dużej uwagi; chcesz prawdopodobnie brać pod uwagę moduły (podobnie jak Zend_Rest_Route), a może nawet opcjonalne baseUrl (nie wiesz, jak ZF radzi sobie z tym wewnętrznie).