Cómo usar URLs amigables con el Servidor Web Incorporado a PHP

Es muy común, desde la versión 5.4 de PHP, usar el servidor que viene incorporado mientras estamos en un ambiente de desarrollo (¿Para qué negarlo? ¡Es sumamente cómodo!).

Un problema que sucede a menudo al utilizarlo es cómo usar URLs amigables.

Por ejemplo, a un sitio web productivo no vas a querer que se acceda mediante algo como:

https://misitio.com/index.php?fecha=2019-06-25&slug_categoria=top10

Más bien vas a preferir algo como:

https://misitio.com/articulos/2019-06-25/top10

¿O no?

El problema es que, en el caso de PHP, las variables que se reciben a través de la URL son accesibles a los scripts a través de la variable $_GET.

Claro que, para que esto suceda, estas URLs deben estar escritas respetando el formato canónico:

  1. La separación entre URLs y parámetros se marca con el caracter «?»
  2. La separación entre nombre del parámetro y valor se marca con el caracter «=»
  3. La separación entre valor de un parámetro y nombre del siguiente se marca con el caracter «&»

La solución a este problema pasa por aplicar lo que se conoce como reglas de re-escritura.

Qué son las reglas de re-escritura

Las reglas de re-escritura son instrucciones que se le dan al servidor web para transformar URLs agradables en otras más útiles.

Básicamente se trata de reglas de mapeo que establecen a qué URL real le corresponde cada URL amigable.

Usualmente estas reglas se escriben utilizando expresiones regulares (Claro que la sintaxis exacta dependerá del software de servidor web que estés utilizando).

Por ejemplo, una regla de re-escritura de Apache se verá de esta forma:

RewriteRule .? http://www.example.com%{REQUEST_URI} [R=301,L] 

En un entorno productivo, las reglas de re-escritura se escriben en algún archivo de configuración del webserver, en desarrollo en cambio, el tema puede no ser tan fácil…

Cómo usar reglas de re-escritura con el servidor incorporado a PHP

El servidor web incorporado a PHP no tiene un mecanismo explícito de re-escritura de URLs, sin embargo, es perfectamente posible el uso de URLs amigables.

El truco es iniciar el servidor web dirigiendo todo el tráfico hacia un archivo en particular.

Por ejemplo:

php -S localhost:8000 router.php

Al hacer esto, todos los pedidos que lleguen a http://localhost:8000 serán atendidos por el archivo router.php.

Nuestra tarea ahora es escribir el código dentro del archivo de modo tal que realice las transformaciones necesarias.

Para ello vamos a apoyarnos en:

  1. La variable $_SERVER[«REQUEST_URI»]
  2. La función preg_match

De la variable $_SERVER[«REQUEST_URI»] obtendremos la URL tal como la escribió el usuario.

Con la función preg_match validaremos si dicha URL tiene una cierta forma y, de ser así, redirigiremos la petición a donde correponda.

Veamos un ejemplo de router:

<?php

$matches = $_GET = [];

if (preg_match('/\/([^\/]+)\/([^\/]+)/', $_SERVER["REQUEST_URI"], $matches)) {
    $_GET['resource_type'] = $matches[1];
    $_GET['resource_id'] = $matches[2];

    error_log( print_r($matches, 1) );
    require 'server.php';
} elseif ( preg_match('/\/([^\/]+)\/?/', $_SERVER["REQUEST_URI"], $matches) ) {
    $_GET['resource_type'] = $matches[1];
    error_log( print_r($matches, 1) );

    require 'server.php';
} else {

    error_log('No matches');
    http_response_code( 404 );
}

En este caso estoy usando la expresión regular /\/([^\/]+)\/([^\/]+)/ para buscar URLs que tengan la forma /algo/otraCosa (O, más concreto: /articulos/deportes) y la expresión /\/([^\/]+)\/?/ para URLs de tipo /algo.

Si la URL efectivamente coincide con alguno de los patrones buscados tomaré las coincidencias y con eso llenaré el arreglo $_GET lo cual, en definitiva logra la transformación de fragmento de URL en parámetro.

Y por último, realizaré el require para delegar el control en el archivo que efectivamente sabrá cómo procesar este request.

No está mal, ¿cierto? 🙂

Un tip extra, por si te estás enloqueciendo con las expresiones regulares, me ayudó mucho usar este verificador: https://regex101.com/

mchojrin

Por mchojrin

Ayudo a desarrolladores PHP a acceder mercados y clientes más sofisticados y exigentes

2 comentarios

    1. Hola Camilo!

      En un servidor de producción deberías usar algún software como Apache, NginX o similar.

      El servidor incorporado a php (a partir de la versión 5.4 si no me equivoco) no requiere ninguna instalación especial pero sólo debe usarse para desarrollo.

¿Te quedó alguna duda? Publica aca tu pregunta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.