2011-03-01 5 views
8

Estoy desarrollando un controlador de reposo con Zend y estoy confundido con el mapeo de urls en el enrutador.Coincidencia de múltiples URL con parámetros usando Zend_Controller_Router_Route_Regex en Zend Framework

Básicamente he leído sobre Zend Router y no pude planificar mis URL para satisfacer las rutas mencionadas.

Estas son algunas de mis direcciones URL que deberían asignarse a los enrutadores.

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

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

Estoy planeando tal que para los patrones de URL a 1 3, "etiquetas" debería ser el controlador y para los patrones de URL 4 a 6, "pings" debería ser el controlador.

Ahora no estoy seguro de cómo configurar los enrutadores de modo que los escenarios anteriores funcionen. Tenga en cuenta que no puedo cambiar estas URL. Puedo ofrecer 100 de mi puntaje de reputación a la buena respuesta.

+1

puedo votar –

+0

¿Por qué tiene/necesita "public/index.php" al inicio de todas estas URL? –

+0

No son obligatorios y los eliminé. Solo me preocupa el enrutamiento de estas URL a sus respectivos controladores y acciones, pasando los parámetros necesarios. –

Respuesta

6

Las dos primeras URL pueden combinarse en un enrutador.

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

Para diferenciar las dos primeras rutas, verifique la presencia del parámetro abc en su controlador de etiquetas. Agregue lo siguiente en su controlador de etiquetas, acción de índice.

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

Del mismo modo, las rutas 4 y 5 se pueden combinar en una ruta.

He explicado para la ruta 6. Para la ruta 3, puede usar la misma lógica.

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

Los parámetros pueden entonces visitada como la siguiente en el controlador pings.

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

Por Ruta 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); 

Los parámetros (? Parte de la URL después) no será manejada en el router. Por defecto, se pasarán a su controlador.

Para obtener un valor de parámetro específico pasado en su URL, use lo siguiente en su controlador.

$this->_getParam('a'); 

La lógica es el uso (. *) En su ruta y asignarles un nombre de parámetro y acceder a ellos en su controlador

+0

@emaillenin Gracias, funcionó a la perfección, pero no pude obtener el formato de expresiones regulares para el quinto caso. ¿Puedes por favor publicar un ejemplo para eso? No pude obtener los parámetros a = 1 & b = 2. –

+0

@dskanth pings.xml es una parte estática de la URL? – emaillenin

+0

Lo siento por llegar tarde, pero sí, pings.xml es la parte estática de la quinta URL, quiero la parte después de eso. –

4

Aquí está un motor de arranque para una pieza de algoritmo que destila el controlador, params indexados, y la extensión de la solicitud, que se podría incorporar en una versión extendida de 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; 
} 

es apenas probó, y por lo tanto no material de producción, por supuesto. Pero debería ayudarte a comenzar.

Lo que esto da que hasta ahora es:
El controlador
La extensión
Los parámetros indexados

Lo que esto no le da es:
La acción (POST, PUT, borrar, etc. . El algoritmo para esto ya está en Zend_Rest_Route::match())
Los parámetros con nombre (Zend_Controller_Request_Http se encarga de eso ya)

EDITAR
Me doy cuenta de que esta respuesta podría considerarse un tanto vaga hasta el momento. El punto es fusionar este algoritmo con el algoritmo match() de Zend_Rest_Route. Pero este código anterior aún necesita mucha atención; también es probable que desee contabilizar los módulos (al igual que Zend_Rest_Route), y tal vez incluso una baseUrl opcional (no estoy seguro de cómo ZF se ocupa de esto internamente).

Cuestiones relacionadas