2012-07-30 26 views
8

Estoy escribiendo una clase que maneja el enrutamiento de mi servicio web PHP pero necesito corregir la expresión regular, y quiero saber cuál sería la forma más eficaz de analizar la URL.Url enrutamiento regex PHP

direcciones URL de ejemplo:

  • poste/usuarios
  • GET/usuarios
  • GET/usuarios & límite = 10 & offset = 0
  • GET/usuarios/búsqueda & palabra clave = Richard
  • GET/users/15/posts/38

Lo que yo quiero crear en PHP para la clase es la siguiente:

$router = new Router(); 
$router->addRoute('POST', '/users', function(){}); 
$router->addRoute('GET', '/users/:uid/posts/:pid', function($uid, $pid){}); 
$target = $router->doRouting(); 

La variable objetivo sería ahora contienen una matriz con:

  • método
  • url
  • método de devolución de llamada

Esto es lo que obtuve hasta ahora:

class Router{ 
    use Singleton; 

    private $routes = []; 
    private $routeCount = 0; 

    public function addRoute($method, $url, $callback){ 
     $this->routes[] = ['method' => $method, 'url' => $url, 'callback' => $callback]; 
     $this->routeCount++; 
    } 

    public function doRouting(){ 
     $reqUrl = $_SERVER['REQUEST_URI']; 
     $reqMet = $_SERVER['REQUEST_METHOD']; 

     for($i = 0; $i < $this->routeCount; $i++){ 
      // Check if the url matches ... 
      // Parse the arguments of the url ... 
     } 
    } 
} 

así que necesito una expresión regular que en primer lugar:

  1. /mainAction /: argumentName/secondaryAction /: secondaryActionName

comprueba si esa es igual al $ reqUrl (ver en el bucle arriba)

  1. Extrae los argumentos, para que podamos usarlos en nuestra función de devolución de llamada.

Lo que intenté yo mismo:

(code should be in the for loop @ doRouting function) 

// Extract arguments ... 
$this->routing[$i]['url'] = str_replace(':arg', '.+', $this->routing[$i]['url']); 

// Does the url matches the routing url? 
if(preg_match('#^' . $this->routes[$i]['url'] . '$#', $reqUrl)){ 
    return $this->routes[$i]; 
} 

Realmente aprecio todo ayuda, muchas gracias.

+0

$routeCount Esto debería funcionar si se puede enmarcar sus argumentos como GET HTTP http://php.net/manual/en/function.parse-url.php – SomeKittens

+0

: //whathaveyoutried.com - Quiero decir, solo pedir una expresión regular sin siquiera intentar algo tú mismo es bastante vago ... – fdomig

+0

@fdomig cierto, agregué lo que probé. No soy flojo, simplemente no soy bueno en expresiones regulares y me quedo en ello jaja: P – onlineracoon

Respuesta

8

esto funciona básicamente ahora.

public function doRouting(){ 
    // I used PATH_INFO instead of REQUEST_URI, because the 
    // application may not be in the root direcory 
    // and we dont want stuff like ?var=value 
    $reqUrl = $_SERVER['PATH_INFO']; 
    $reqMet = $_SERVER['REQUEST_METHOD']; 

    foreach($this->routes as $route) { 
     // convert urls like '/users/:uid/posts/:pid' to regular expression 
     $pattern = "@^" . preg_replace('/\\\:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', preg_quote($route['url'])) . "[email protected]"; 
     $matches = Array(); 
     // check if the current request matches the expression 
     if($reqMet == $route['method'] && preg_match($pattern, $reqUrl, $matches)) { 
      // remove the first match 
      array_shift($matches); 
      // call the callback with the matched positions as params 
      return call_user_func_array($route['callback'], $matches); 
     } 
    } 
} 

PS: Usted no necesita el atributo

+0

Muchas gracias, sin embargo, hay un problema con su expresión regular: "/ users /: uid /" se enrutaría a lo mismo que "/ users /: uid/messages /: mid ", ¿así que tenemos que verificar en algún lado si es completamente igual no parcialmente en la expresión regular? – onlineracoon

+0

corrigió el problema, debería funcionar ahora (no probado) – MarcDefiant