Leccion 46 de 75 8 min de lectura

Fibers

Fibers son una caracteristica de PHP 8.1 que permite la ejecucion concurrente cooperativa. Son la base para bibliotecas asincronas y rara vez se usan directamente.

¿Que son los Fibers?

Un Fiber es un bloque de codigo que puede pausarse y reanudarse. A diferencia de los hilos, los Fibers son cooperativos: el codigo decide cuando cede el control.

PHP
<?php

declare(strict_types=1);

$fiber = new Fiber(function (): void {
    echo "1. Inicio del Fiber\n";

    // Pausar y devolver control al llamador
    $valor = Fiber::suspend('pausado');

    echo "3. Reanudado con: $valor\n";
});

// Iniciar el Fiber
$resultado = $fiber->start();
echo "2. Fiber pausado, retorno: $resultado\n";

// Reanudar el Fiber
$fiber->resume('datos del exterior');
echo "4. Fiber terminado\n";

// Salida:
// 1. Inicio del Fiber
// 2. Fiber pausado, retorno: pausado
// 3. Reanudado con: datos del exterior
// 4. Fiber terminado

Metodos principales

PHP
<?php

declare(strict_types=1);

$fiber = new Fiber(function (): string {
    $entrada = Fiber::suspend('esperando');
    return "Resultado: $entrada";
});

// start(): inicia el Fiber, retorna lo que suspend() envia
$suspendido = $fiber->start();

// resume($valor): reanuda pasando un valor
$retorno = $fiber->resume('hola');

// getReturn(): obtiene el valor retornado
echo $fiber->getReturn(); // "Resultado: hola"

// Estados del Fiber
$fiber2 = new Fiber(fn () => Fiber::suspend());
echo $fiber2->isStarted();   // false
echo $fiber2->isSuspended(); // false
echo $fiber2->isRunning();   // false
echo $fiber2->isTerminated(); // false

$fiber2->start();
echo $fiber2->isSuspended(); // true

Caso de uso: multiples tareas

PHP
<?php

declare(strict_types=1);

function crearTarea(string $nombre, int $pasos): Fiber
{
    return new Fiber(function () use ($nombre, $pasos): string {
        for ($i = 1; $i <= $pasos; $i++) {
            echo "$nombre: paso $i de $pasos\n";
            Fiber::suspend();
        }
        return "$nombre completada";
    });
}

// Crear varias tareas
$tareas = [
    crearTarea('Tarea A', 3),
    crearTarea('Tarea B', 2),
    crearTarea('Tarea C', 4),
];

// Iniciar todas
foreach ($tareas as $tarea) {
    $tarea->start();
}

// Ejecutar en "paralelo" (intercalando)
while (true) {
    $activas = array_filter($tareas, fn ($f) => !$f->isTerminated());
    if (empty($activas)) {
        break;
    }
    foreach ($activas as $tarea) {
        if ($tarea->isSuspended()) {
            $tarea->resume();
        }
    }
}

// Salida intercalada:
// Tarea A: paso 1 de 3
// Tarea B: paso 1 de 2
// Tarea C: paso 1 de 4
// Tarea A: paso 2 de 3
// ...

Uso en la práctica

En la practica, raramente usaras Fibers directamente. Son la base para bibliotecas como:

  • ReactPHP: programacion asincrona orientada a eventos
  • Amp: concurrencia con promesas y coroutines
  • Swoole: servidor HTTP de alto rendimiento
PHP Ejemplo conceptual con async/await
<?php

declare(strict_types=1);

// Esto es pseudo-codigo para ilustrar el concepto
// En la practica, usarias una biblioteca como Amp

/*
use Amp\async;
use Amp\Future;

// Con bibliotecas basadas en Fibers
$resultados = Future\await([
    async(fn () => fetchUrl('https://api1.example.com')),
    async(fn () => fetchUrl('https://api2.example.com')),
    async(fn () => fetchUrl('https://api3.example.com')),
]);

// Las 3 peticiones se ejecutan "en paralelo"
// Fibers permiten que mientras una espera respuesta,
// las otras pueden continuar
*/
Nota importante

Fibers son una caracteristica de bajo nivel. Para la mayoria de casos, usaras bibliotecas que los aprovechan internamente. No necesitas entender Fibers en profundidad para usar PHP 8.

Ejercicios

Ejercicio 1: Fiber basico

Crea un Fiber que cuente del 1 al 5, suspendiendo despues de cada numero. El codigo principal debe imprimir un separador entre cada reanudacion.

Ver solucion
PHP
<?php

declare(strict_types=1);

$contador = new Fiber(function (): void {
    for ($i = 1; $i <= 5; $i++) {
        echo "Numero: $i\n";
        if ($i < 5) {
            Fiber::suspend();
        }
    }
});

$contador->start();

while ($contador->isSuspended()) {
    echo "---\n";
    $contador->resume();
}

echo "Fin\n";

Ejercicio 2: Comunicacion bidireccional

Crea un Fiber que reciba numeros via resume() y los acumule. Cuando reciba 0, debe terminar y retornar la suma total.

Ver solucion
PHP
<?php

declare(strict_types=1);

$sumador = new Fiber(function (): int {
    $suma = 0;
    while (true) {
        $numero = Fiber::suspend($suma);
        if ($numero === 0) {
            return $suma;
        }
        $suma += $numero;
    }
});

$sumador->start();
$sumador->resume(10);  // suma = 10
$sumador->resume(20);  // suma = 30
$sumador->resume(5);   // suma = 35
$sumador->resume(0);   // termina

echo "Total: " . $sumador->getReturn(); // 35

¿Te está gustando el curso?

Cursos premium con proyectos reales y soporte.

Descubrir cursos premium