2011-03-01 7 views
8

Sto sviluppando un Rest Controller con Zend e sono confuso con la mappatura degli URL al router.Corrispondenza di più URL con parametri utilizzando Zend_Controller_Router_Route_Regex in Zend Framework

Fondamentalmente ho letto su Zend Router e non ho potuto pianificare i miei url per soddisfare i percorsi indicati.

Questi sono alcuni dei miei URL che devono essere mappati sui router.

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

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

sto progettando tale che per i modelli URL 1 a 3, "tag" dovrebbe essere il controller e per i pattern url da 4 a 6, "ping" dovrebbe essere il controller.

Ora non sono sicuro su come configurare i router in modo che gli scenari sopra funzionino. Nota che non posso cambiare questi URL. Posso offrire 100 del mio punteggio di reputazione alla buona risposta.

+1

posso votare su –

+0

Perché hai/bisogno di "public/index.php" all'inizio di tutti questi URL? –

+0

Non sono obbligatori e li ho rimossi. Sono solo preoccupato per il routing di questi URL ai rispettivi controllori e azioni, passando i parametri necessari. –

risposta

6

I primi due URL possono essere combinati su un router.

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

Per differenziare i primi due percorsi, verificare la presenza del parametro abc nel controller dei tag. Aggiungi quanto segue nel tuo controller tag, azione indice.

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

Analogamente, i percorsi 4 e 5 possono essere combinati in un unico percorso.

Ho spiegato per il percorso 6. Per il percorso 3, è possibile utilizzare la stessa logica.

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

È possibile accedere ai parametri come segue nel controller di ping.

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

Per Percorso 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); 

I parametri (? Parte dell'URL dopo) non saranno trattati nel Router. Per impostazione predefinita, verranno passati al controller.

Per ottenere un valore di parametro specifc passato nell'URL, utilizzare quanto segue nel controller.

$this->_getParam('a'); 

La logica è l'uso (. *) Nel vostro percorso e assegnare loro un nome del parametro e accedervi nel controllore

+0

@emaillenin Grazie, ha funzionato perfettamente, ma non ho potuto ottenere il formato regex per il quinto caso. Puoi per favore postare un esempio per questo? Non sono riuscito a ottenere i parametri a = 1 & b = 2. –

+0

@dskanth pings.xml è una parte statica dell'URL? – emaillenin

+0

Ci scusiamo per il ritardo, ma sì, pings.xml è la parte statica del quinto URL, voglio la parte successiva. –

4

Ecco un antipasto per un pezzo di algoritmo che distilla i controller, params indicizzati, ed estensione dalla richiesta, che si può incorporare in una versione estesa di 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; 
} 

e 'poco testato, e quindi non materiale di produzione, naturalmente. Ma dovrebbe iniziare.

ciò che questo non darà finora è:
Il controller
L'estensione
I parametri indicizzati

Che questo non darvi è:
L'azione (posta, inserire, cancellare, ecc . L'algoritmo per questo è già in Zend_Rest_Route::match())
I parametri denominati (Zend_Controller_Request_Http si occupa di questo già)

EDIT
Mi rendo conto che questa risposta potrebbe essere considerata un po 'vaga finora. Il punto è di unire questo algoritmo con l'algoritmo match() di Zend_Rest_Route. Ma questo codice sopra richiede ancora molta attenzione; anche tu vuoi rendere conto dei moduli probabilmente (come fa Zend_Rest_Route), e forse anche un baseUrl opzionale (non sono sicuro di come ZF si occupi di questo internamente in realtà).

Problemi correlati