+34 687 770 998 hector.ayestaran@gmail.com





Blog


18
JUN
2018

Node.js: Cómo desarrollar una webapp con PHP como modelo (MVC)

Node.js es una runtime fantástica que nos permite crear aplicaciones muy rápidas y con mínimos errores de HTTP en comparación con Apache. Además, el lenguaje utilizado es Javascript, con el cual estamos tan familiarizados que hasta soñamos con él. Sin embargo, PHP es un lenguaje que brinda características estupendas y permite una arquitectura moderna que a mi juicio es superior a la de Node.js.
La buena noticia es que no tenemos por qué elegir entre ambas. Gracias al módulo para Node.js exec-php podemos combinarlos. En este artículo os mostraré como hacerlo mediante una demo básica en Windows. Cabe decir que lo que vamos a ver no se inscribe en un esquema MVC canónico, pero he estimado aceptable el llamar modelo a la lógica PHP, puesto que mi idea es desarrollar en dicha lógica aquello que sería el modelo en un esquema MVC tradicional, la cual a su vez, por escalabilidad, deberá estar compuesta por controlador y modelo (controlador PHP y modelo PHP).

El primer paso será crear el proyecto Node para la demo. Crearemos el directorio en la ubicación que deseemos y haremos uso del módulo create-node-project para crear automáticamente todos los subdirectorios y archivos propios de un proyecto Node.js. Solo tenemos que ubicarnos en el directorio de instalación de Node en la línea de comandos y ejecutar:

node node_modules/create_node_project.js C:\nodejs\exec-php

Acto seguido, en la línea de comandos, nos ubicaremos en el directorio de nuestro nuevo proyecto e instalaremos el módulo exec-php:

npm install exec-php

Ahora vamos a crear el archivo PHP de pruebas, dentro del directorio public/php y lo llamaremos test.php. Dicho archivo tan solo realizará un echo: el clásico ¡Hola mundo!. El código de nuestra webapp Node (para los más despistados el archivo server.js) será el siguiente:

var http = require('http');
var fs = require('fs');

var server = http.createServer(function(req, res) {
		
	res.writeHead(200);

	var execPhp = require('exec-php');

	execPhp(__dirname +'/public/php/test.php', 'php.exe', function(error, php, output) {
		res.end(output);
	});
});

console.log("Servicio en escucha en puerto 8080");
server.listen(8080);

Hora de lanzar nuestra webapp:

node server.js

Acto seguido navegamos a la URL http://127.0.0.1:8080 y ¡tachan! Obtenemos un precioso hola mundo escupido por nuestro PHP.

Los más avispados se estarán preguntando ya cómo pasar parámetros a test.php, si el QueryString de toda la vida funcionará o no. Bueno, pues la respuesta es no. Si añadimos parámetros GET a la ruta de test.php, Node no lo va a encontrar. Recordemos que en un entorno Apache, es el propio servidor web quien parsea la URL y alimenta las superglobales de PHP.

Entonces, ¿cómo podemos pasar parámetros a nuestro archivo PHP? De la manera menos esperada: Si nos fijamos en el código, el tercer argumento de la función execPhp es un callback que a su vez recibe como segundo argumento un objeto llamado php (el argumento anterior al callback, es el binario de PHP que utilizaremos a modo de pseudo-cgi). Dicho objeto php, albergará como métodos todas las funciones globales que hayamos implementado en test.php, y podremos invocarlas en nuestro código js.
El siguiente argumento del callback, output, contiene la salida de test.php, es decir, aquello que pinta en pantalla.

Veamos un ejemplo. Añadiremos a test.php la siguiente función:

<?
//echo '¡Hola mundo!';

function retornar($arg) {
	return 'He recibido los argumentos: '. $arg[0] . $arg[1];
}

El código de nuestro server.js será:

var http = require('http');
var fs = require('fs');

var server = http.createServer(function(req, res) {
		
	res.writeHead(200);

	var execPhp = require('exec-php');

	execPhp(__dirname +'/public/php/test.php', 'php.exe', function(error, php, output) {
		
		php.retornar(['¡Hola', ' mundo!'], null, function(error, result, output, printed) {
			 res.end(result);
		});
	});
});

console.log("Servicio en escucha en puerto 8080");
server.listen(8080);

Como podemos observar, enviamos los parámetros a la función retornar en el primer argumento a modo de array. Una vez allí, los recogeremos y utilizaremos como cualquier array de PHP.

Reiniciamos nuestro servicio (Ctrl + C para detenerlo) y refrescamos la página en nuestro navegador para ver resultado.

Una de las virtudes de este sistema es que para visualizar los cambios realizados en la lógica PHP, no hace falta reiniciar el servicio Node.

Respecto al grado de implementación que puede soportar nuestro modelo PHP, decir que no he experimentado a fondo, pero clases e includes se pueden utilizar sin problemas.

Finalmente, cabe mencionar que no podremos utilizar la mayoría de superglobales PHP, al ser estas alimentadas por un servidor web, Apache por ejemplo. Sí podremos utilizar la superglobal $_SERVER, pero en vez de parámetros propios del entorno web, obtendremos variables de entorno del sistema. Desconozco que implicaciones podría tener a nivel de seguridad.

Esto es todo. Un saludo.

Volver