Desde la versión 5.4 de PHP, contamos con una nueva herramienta en nuestro arsenal: un Servidor Web interno en PHP, que nos permite realizar pruebas de una manera sencilla, sin la necesidad de tener un servidor web (ya sea NginX o Apache) corriendo de manera separada.
En este artículo voy a intentar explicar brevemente cómo funciona este servidor web, que opciones tenemos para configurarlo, y finalmente, les mostraré un ejemplo sobre como podemos crear un pequeño proyecto.
Comencemos por lo básico
El servidor Web se ejecuta desde línea de comandos, ya sea en una consola (Mac/Linux) o desde PowerShell (Windows). Para verificar que ciertamente tenemos una versión igual o superior a 5.4, deberíamos ejecutar php -v
y comprobar esto.
Primero, creemos un archivo info.php que ejecute una llamada a phpinfo()
y guardémoslo en un directorio vacío.
1 | <?php phpinfo(); ?> |
A continuación, ya podemos ejecutar el servidor web, que de la manera más básica, se inicia de esta manera
1 | $ php -S localhost:8000 |
Esto iniciará el servidor web, utilizando como raíz el directorio en el que nos encontramos actualmente, y publicando el servicio en la dirección localhost
y en el puerto 8000.
1 | php -S localhost:8000 PHP 5.5.20 Development Server started at Thu Jul 16 23:13:59 2015 Listening on http://localhost:8000 Document root is /var/www/phpservertest Press Ctrl-C to quit. |
Efectivamente, si abrimos un navegador web, y nos dirigimos a http://localhost:8000/info.php
podemos acceder a la información de phpinfo()
y comprobar que todo está funcionando correctamente.
Opciones de la línea de comandos.
Como ya vimos, la opción -S
es la que realiza toda la magia y lanza el servidor web, pero hay ciertas opciones que nos permiten modificar este comportamiento.
Si ejecutamos el servidor con la opción -t
, podríamos indicarle otro directorio como el directorio raiz del servidor, efectivamente pudiendo soportar cualquier directorio en nuestro disco rígido.
1 | php -S localhost:8000 -t ./public_html PHP 5.5.20 Development Server started at Thu Jul 16 23:25:15 2015 Listening on http://localhost:8000 Document root is /var/www/phpservertest/public_html Press Ctrl-C to quit. |
Una opción útil en este caso, que no es propia del servidor web sino que existe hace mucho tiempo en el intérprete de PHP, es -c
que nos permite indicar un archivo de configuración distinto al default. Así, si tuviéramos dentro de nuestra aplicación, un archivo temporal de configuración, podríamos crear un ambiente de testing con distinta configuración a un ambiente de producción:
1 | php -S localhost:8000 -c etc/dev.ini |
Por último, el servidor web acepta como parámetro un archivo.php, pero al contrario de lo que pensaríamos, no lo ejecuta directamente como el archivo raiz de la aplicación. Este archivo.php es considerado como un Router, que se ejecutará automáticamente antes de cada petición que realicemos hacia cualquier recurso.
Si este archivo retorna false
entonces el servidor web procesará ese archivo normalmente. Si este archivo retorna cualquier otra cosa que no sea false
entonces ese contenido será lo que el servidor responde, independientemente del recurso que se intente acceder via web.
Volviendo al ejemplo anterior donde mostrábamos el resultado del archivo info.php
si accedíamos mediante un navegador a http://localhost:8000/info.php
, veamos que sucede si creamos un archivo router.php
que se ejecute antes de cada petición.
1 | <?php |
Ya no podemos acceder a la información dentro de info.php
.
De esta manera, podemos controlar brevemente que tipos de archivos se pueden ejecutar en nuestro servidor web de desarrollo, o podemos realizar otros tipos de lógica, como indicar que parte de un sitio se cargará si intentamos acceder a distintas urls. Este trabajo generalmente se llevaría a cabo en un servidor web como Apache dentro del archivo .htaccess
o en NginX dentro de nginx.conf
.
Un proyecto de ejemplo
Vamos a suponer que estamos desarrollando un proyecto web, y lo estructuramos de manera más o menos acorde a los estándares actuales. Los directorios que tendríamos, por ejemplo, serían los siguientes:
1 | | MiWebApp |- /public | |- /css | | |- style.css | |- /errors | | |- 403.html | | |- 404.html | | |- 500.html | |- index.php |- /src | |- /Model | | |- UserModel.php | |- App.php |- /tests | |- AppTest.php |
- /public: En esta carpeta guardamos todos los archivos que estarán en la raiz de un servidor web. Todo lo que queremos que sea accesible a “Internet”.
- /src: Aquí guardamos la lógica correspondiente a la aplicación que estamos creando.
- /tests: Si escribimos Tests Unitarios, entonces aquí es donde deberíamos guardarlos.
Hasta aquí, nada nuevo.
Pero si queremos agregar la posibilidad de utilizar el servidor web interno de PHP, entonces agregaremos unos directorios extras al proyecto (emulando los directorios de sistemas unix/linux):
- /etc: Utilizado para almacenar archivos de configuración extras.
- /bin: Archivos ejecutables desde línea de comandos. Usaremos este directorio para guardar nuestro router y un script.
Esta es la forma que tendrá nuestro proyecto con estos nuevos directorios:
1 | | MiWebApp |- /bin | |- init.sh | |- router.php |- /etc | |- dev.ini |- /public | |- /css | | |- style.css | |- /errors | | |- 403.html | | |- 404.html | | |- 500.html | |- index.php |- /src | |- /Model | | |- UserModel.php | |- App.php |- /tests | |- AppTest.php |
Archivo de configuración
Primero, creemos un archivo configuración inicial, al estilo de un php.ini
, pero con seteos que solo serán válidos cuando estemos desarrollando. Por ejemplo, podemos activar todos los errores:
1 | error_reporting = E_ALL |
El Router
A continuación, dentro de la carpeta bin
podremos alojar un archivo PHP con la lógica del router que vimos antes. Al utilizar un archivo de router con el servidor web, perdemos la capacidad por defecto de obtener información sobre cada petición en la consola, así que debemos incorporar esta funcionalidad. Creamos para ello, una función llamada logger
, además de realizar algunos chequeos (lean los comentarios en el archivo):
1 | <?php |
No olvidemos entonces crear el archivo public/errors/404.html
para que todo esto funcione
1 | <!doctype html> |
Script de lanzamiento
Ya solo nos queda crear un pequeño script para lanzar el servidor, que guardaremos dentro del directorio bin
.
1 | #! /bin/bash |
Antes de continuar, deberíamos asegurarnos que este archivo tenga los permisos necesarios para ser ejecutado. Esto lo logramos, ubicados desde el directorio raíz, con el siguiente comando:
1 | chmod +x ./bin/init.sh |
Para lanzar el servidor ya solamente nos queda invocar el siguiente comando:
1 | ./bin/init.sh |
Finalizando
Ciertamente, es muy sencillo comenzar a utilizar el servidor web de PHP para tener un ambiente rápido donde testear la aplicación, o bien, continuar desarrollándola. Este ejemplo en particular es muy básico, pero algunas mejoras que se pueden realizar son:
asegurarnos que el archivo router.php pueda chequear los accesos contra un listado permitido de direcciones IP. De no estar dentro de una lista, enviar un error tipo 403 Not allowed.
El error 404, podría dar algo más de información relacionada a la petición, para ello, en vez de un archivo 404.html podríamos incluir un archivo 404.php que tome las variables del array
$_SERVER
y arme una página más informativa.
Les dejo todo el código con el que estuvimos trabajando preparado para que lo descarguen y continúen realizando pruebas.
Hasta la próxima.