2009-12-08 22 views
15

Estoy debatiendo encaminar mis peticiones con una de las dos opciones:Mod-Rewrite o enrutador PHP?

Opción 1: Ruta de captura sencilla con Mod-Rewrite y el embudo escrita $_GET ruta a index.php para la carga ...

#default routing 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule ^blog/([0-9]+)?$ index.php?rt=blog&params=$1 [L,QSA] 
// ..more custom routes, and then a default route 
RewriteRule ^([A-Za-z]+)/([A-Za-z]+)/(.*)?$ index.php?rt=$1/$2&params=$3 [L,QSA] 

opción 2: simplemente peticiones a Front Controller, y crear una clase PHP enrutamiento para manejar el enrutamiento ...

#default routing 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule ^(.*)$ index.php?rt=$1 [L,QSA] 

/* --- on front controller, process $_GET['rt'] --- */ 

al final de la jornada, que se desarrollará más rápido, más fácil para hacer efectivo, y serán más fáciles ¿mantener?

¿Alguna otra idea?

NOTA: No estoy ejecutando un marco conocido. Estoy construyendo mi propio patrón MVC para aprenderlo.

+0

¿qué es lo que quiere decir con seguridad? –

+0

Bueno, yo reallmente asumí que hay medidas que tomar para asegurarme de que mi sistema/framework/etc no tenga ninguna vacante que no sepa. simplemente suponiendo que soy más ingenuo de lo que esperaba – johnnietheblack

+0

Aplaudo sus esfuerzos. –

Respuesta

16

Por lo general, en marcos MVC, este tipo de cosas generalmente se maneja mejor con un controlador frontal (llamado index.php o similar). Utiliza mod_rewrite para ocultar index.php de todas las URL para que los usuarios vean rutas limpias.

También es mucho más fácil de manejar en PHP que en las directivas de reescritura de Apache. PHP es mucho más flexible y fácil de escribir/comprender. No estoy seguro de haber visto mod_rewrite como el único motor de enrutamiento para cualquier estructura web, ahora que lo pienso.

Su segundo fragmento de código es el camino a seguir para sus directivas de reescritura.

+1

Definitivamente de acuerdo. Además, las reglas múltiples para realizar la misma tarea básica serán difíciles de manejar y comprender después de un tiempo. Si nos fijamos en cualquiera de los principales frameworks php (vale, tal vez no, solo uso Symfony y Zend, jeje) solo usan la reescritura para obtener la "url bonita" para el controlador y luego implementan el enrutamiento internamente en una clase de enrutamiento de somesort para descifrar los parámetros reales basados ​​en todo tipo de reglas complejas. Id seguir este enfoque si yo fuera tú. – prodigitalson

+4

Estoy de acuerdo. Los sitios en los que he trabajado con más de 30 rutas de reescritura personalizadas siempre fueron un problema. PD: agregue algunas rutas para que su servidor web maneje las imágenes, js y css. Vea el ejemplo de zend frameworks htaccess - http://framework.zend.com/wiki/display/ZFDEV/Configuring+Your+URL+Rewriter – mozillalives

+0

@MarcW Me gusta su respuesta. ¿Tal vez podrías recoger 300 puntos al dar mi pregunta a la buena vieja universidad? http://stackoverflow.com/questions/42172228/is-this-how-an-mvc-router-class-typically -works –

0

Yo también estoy en el proceso de construir un sistema LAMP MVC desde cero.

MVC Router Class Question

Rendimiento

Después de haber creado un script de shell bash para compilar Apache 2.4.x de la fuente, se observa que un Compatible biblioteca de expresiones regulares de Perl se cuece en el proceso. Cada vez que se use el código de expresión regular, la respuesta del servidor http será más lenta. Por lo tanto, la opción número uno es un no ir si el rendimiento es su problema. Hay un costo para los análisis involucrados con las expresiones regulares. El servidor web Apache toma prestada la lógica para expresiones regulares. No es el código local de Apaches.

Seguridad

seguridad es un tema diferente. En primer lugar, nada acerca de reescribir las URL las hace seguras. Es simple seguridad a través de la oscuridad y hacer que las cosas se vean bonitas en el lado del cliente. De vez en cuando, los agujeros de seguridad se encuentran en el código del motor de expresión regular. Por lo tanto, en términos de seguridad real, se queda en la misma posición básica en la que estaría sin ninguna reescritura: las personas o los bots pueden enviar cosas malas a su servidor y necesita una forma de filtrar y validar los datos de manera sistemática. Asegúrese de filtrar y validar todas las entradas, especialmente cualquier parte de la cadena de consulta reescrita que desee utilizar.

Por lo tanto, la opción número uno presenta una interfaz más limpia (INPUT_GET/$_GET) para iniciar sus tareas de seguridad. La opción número dos requiere (si está tratando de ser minucioso) que filtre y valide toda la cadena como primer paso. El segundo paso (en general) será dividir y extraer lo que esperas reunir de la cadena más grande.

De nuevo, debe filtrar y validar cada pieza de la cadena. Por lo tanto, si bien es más manejable (más fácil, conveniente) filtrar/validar/desglosar/extraer/la cadena más grande en PHP (digamos, con un método en clase de seguridad de algún tipo), aún necesita hacer el trabajo para cada pieza para cada solicitud La opción número uno le ahorra la molestia de tener que dividir la cadena más grande por el costo de ejecutar el motor de expresiones regulares en cada solicitud. Pero, en su mayor parte, puede comenzar a filtrar y validar los elementos que espera recibir en INPUT_GET o $_GET.

Tenga en cuenta, sin embargo, que la opción uno es principalmente para personas que realmente entienden cómo funcionan las expresiones regulares y cómo esto se aplica a posibles URL que su servidor puede recibir. Si necesita más de un RewriteRule, podría ser para que pueda tener algo como esto (u otras razones) entrar al servidor.

index.php?0=model 

index.php?0=model&1=method 

index.php?0=model&1=method&2=methodArgs 

Esto hace que sea más fácil filtrar y validar sus entradas. Sin embargo, tenga en cuenta que la última línea implica que aún puede necesitar dividir líneas y filtrar/validar más (pero puede que no tenga que suceder en cada solicitud, como ocurre en la opción número 1).

Código de ejemplo: Obtención de parámetros de URL utilizando la opción 2 (inicio en la parte inferior!)

Nota: Estas son sólo algunas cosas a tener en cuenta, no "la" forma de hacerlo.

const QS_ARRAY_LIMIT = 3; 

private function getPairValue($delimiter, $string) 
{ 
    return explode('$delimiter', $string)[1]; //Get the value for a pair. 
} 

private function isMultiValuedQueryString() 
{ 
    return (mb_strpos($this->queryStr, '&', 0, 'UTF-8') > 2); 
} 

private function getAllowedPairs($argsStr) 
{ 
    $pairs = explode('&', $argsStr); 
    $numPairs = count($pairs); 

    if($numPairs > self::QS_ARRAY_LIMIT) 
    { 
     throw new SecurityException("Too many query string pairs ({$numPairs}) submitted to the router.\n"); 
    } 

    return $pairs; 
} 

private function isQueryStrPair($pair) 
{ 
    $equalPos = null; 
    $pairLength = mb_strlen($pair, 'UTF-8'); 

    if($pairLength < 3) 
    { 
     throw new SecurityException("Query string pair is too short: Length: {$pairLength}!, Suspect: {$pair}\n"); //Sends to '/' 
    } 

    $equalPos = mb_strpos($pair, '=', 0, 'UTF-8'); 

    if($equalPos === 0) //The first position. 
    { 
     throw new SecurityException("Query sting pair cannot *start* with an equal sign (=): Suspect: {$pair}\n"); //Sends to '/' 
    } 

    if($equalPos === ($pairLength - 1)) //The last position. 
    { 
     throw new SecurityException("Query sting pair cannot *end* with an equal sign (=): Suspect: {$pair}\n"); //Sends to '/' 
    } 

    return true; 
} 

private function getQueryStringArgs($url) 
{ 
    $delimiter = '?'; 

    if(mb_strpos($url, $delimiter, 0, 'UTF-8') > 0) 
    { 
     return $this->getPairValue($delimiter, $url); 
    } 

    throw new RuntimeException("Malformed URL passed to query string parser."); 
} 

private function associateArgPairs(array $argPairs, array $values) 
{ 
    $i = 0; 

    foreach($argPairs as $key => &value) 
    { 
     if(isset($values[$i])) 
     { 
      $value[$key] = $values[$i]; 
      ++$i; 
     } 
    } 

    return $argPairs; 
} 

private function getQueryStrValues($url) 
{ 
    $delimiter = '='; 
    $argPairs = ['model' => null, 'method' => null, 'methodArgs' => null] 
    $inputValues = []; 
    // ================================================= 
    // Valid query strings might look like (amongst many combinations): 
    // 
    // index.php?arg1=foo&agr2=bar&arg3=/baz/bang/boom 
    // 
    // Or, just one pair with no ampersand,'&'. 
    // 
    // index.php?arg1=foo 
    // ================================================== 

    // Get everything after the question mark, '?'. 
    $queryStringArgsStr = $this->getQueryStringArgs($url); 

    if($this->isMultiValuedQueryString($queryStringArgsStr)) //Check if '&' exists. 
    { 
     foreach($this->getAllowedPairs($queryStringArgsStr) as $pair) 
     { 
      if($this->isQueryStrPair($pair)) 
      { 
       //Get the value for each pair., using '=' as the string delimiter. 
       $inputValues[] = $this->getPairValue($delimiter, $pair); 
      } 
     } 
    } 
    else 
    {  
     if($this->isQueryStrPair($queryStringArgsStr)) 
     { 
      $inputValues[] = $this->getPairValue($delimiter, $queryStringArgsStr); //Get the value for each pair. 
     } 
    } 

    return $this->associateArgPairs($argPairs, $inputValues); 

    //Remember, you will still need to split up $argPairs[$methodArgs] if necessary. 
    //With option #1, you could start closer to this point, 
    //and hence filter and validate sooner. 
} 

Resumen

Si la seguridad es su principal preocupación (es decir, la interfaz en su esquema de seguridad), de tripas corazón y usar la opción número uno. Aprender mod_rewrite y reescritura de URL te hace bastante poderoso. ¿Por qué dejar ese poder sobre la mesa? Apache es un animal extraño a la hora de configurarlo. Pero, si comprende las URL y las expresiones regulares, le digo hombre/mujer y voy por ello. :-) Si la velocidad, la comprensión y la facilidad de uso son sus principales preocupaciones, busque la opción número uno. Hay fanáticos que quieren que todo esté codificado en PHP, pero debes juzgar por ti mismo cuáles son los pros y los contras de ambas situaciones.

Actualización: Mi mal. Este código funcionaría mejor para la opción número 1. En la opción número 2, 1 = bla, donde blah sería algo así como /trt/43ff/3335/f/3/fr3r/ o lo que sea. No tendrás que buscar ampersands.

PHP: filter_inpur_array(), (use INPUT_GET)

PHP: Superglobals

PHP: explode()

PHP: foreach (array_expression as $key => $value)

PHP: Multibtye String Functions