Programación asíncrona en PHP: guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción a la programación asíncrona en PHP

Tradicionalmente, PHP se considera un lenguaje síncrono: cada solicitud se ejecuta secuencialmente, bloqueando la ejecución hasta que se completa una operación de entrada/salida (por ejemplo, leer un archivo o consultar una base de datos). Sin embargo, con la creciente popularidad de las aplicaciones web de alta carga y los microservicios, surgió la necesidad de manejar decenas de miles de conexiones simultáneas sin escalar la cantidad de procesos. La programación asíncrona resuelve este problema, permitiendo ejecutar operaciones de manera concurrente dentro de un solo hilo.

En esta guía, analizaremos cómo funciona la asincronía en PHP, qué herramientas están disponibles y cómo construir aplicaciones no bloqueantes correctamente. Aprenderá sobre generadores, corrutinas, las bibliotecas ReactPHP, Amp y Swoole, así como la nueva extensión Fibers.



Fundamentos de la asincronía: Event Loop y entrada/salida no bloqueante

La programación asíncrona se basa en el concepto de Event Loop (bucle de eventos). Es un bucle infinito que espera y procesa eventos: solicitudes de red, finalización de operaciones de entrada/salida, temporizadores. En lugar de esperar a que se complete una operación, el código registra un callback que se ejecuta cuando los datos están listos. Esto evita desperdiciar tiempo de CPU en espera.

PHP tradicionalmente utiliza funciones bloqueantes (por ejemplo, file_get_contents() o sleep()). Para trabajar de forma asíncrona, es necesario reemplazarlas con alternativas no bloqueantes. Aquí hay un ejemplo simple usando la biblioteca ReactPHP:

<?phprequire 'vendor/autoload.php';

use React\\EventLoop\\Factory;use React\\Promise\\Promise;

$loop = Factory::create();

// Lectura asíncrona de archivo$promise = new Promise(function ($resolve, $reject) use ($loop) { $loop->addTimer(0.001, function () use ($resolve) { $content = file_get_contents('/etc/hosts'); $resolve($content); });});

$promise->then(function ($data) { echo "Leído: " . strlen($data) . " bytes";});

echo "Este código se ejecutará inmediatamente, sin esperar la lectura del archivo";$loop->run();?>

En este ejemplo, addTimer registra una tarea que se ejecutará en el siguiente tick del bucle. El Event Loop no se bloquea, y vemos el mensaje de inmediato, mientras que el resultado de la lectura aparece más tarde.



Generadores y corrutinas: control del flujo de ejecución

Los generadores (yield) aparecieron en PHP 5.5 y permiten pausar la ejecución de una función, devolviendo valores intermedios. Sobre esta base se construyen las corrutinas — hilos ligeros que pueden ceder el control voluntariamente. En combinación con el Event Loop, los generadores permiten escribir código que parece síncrono, pero se ejecuta de forma asíncrona.

Veamos un ejemplo con la biblioteca Amp, que utiliza corrutinas:

<?phprequire 'vendor/autoload.php';

use Amp\\Loop;use Amp\\Delayed;

// Corrutina asíncrona$coroutine = function () { echo "Inicio de la corrutina"; // Nos pausamos por 1 segundo sin bloquear yield new Delayed(1000); echo "Ha pasado 1 segundo"; yield new Delayed(500); echo "Han pasado otros 0.5 segundos";};

Loop::run(function () use ($coroutine) { // Ejecutamos la corrutina $result = yield from $coroutine(); echo "Corrutina finalizada";});?>

En este código, yield new Delayed(1000) pausa la ejecución de la corrutina, devolviendo el control al Event Loop. Después de 1 segundo, la ejecución se reanuda desde el mismo punto. Esto permite manejar miles de estas corrutinas simultáneamente, sin crear nuevos procesos.



Bibliotecas y herramientas para PHP asíncrono

Para trabajar con asincronía en PHP, existen varias bibliotecas maduras. Veamos las tres más populares.

ReactPHP

ReactPHP es la biblioteca más antigua y conocida. Proporciona un Event Loop, Promises (análogas a las de JavaS

Blogs

Book Recommendations