0Pricing
PHP Academy · Leçon

Fibers de PHP 8.1

Mettez en pause et reprenez l’exécution avec les Fibers natives.

Fibers de PHP 8.1 est une leçon PHP Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage PHP Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours PHP Academy comprend 4 leçons au total.

Ce que les fibres vous apportent

PHP 8.1 a ajouté les Fibres : une primitive du noyau qui permet de mettre en pause une pile d’appels en cours et de la reprendre plus tard, depuis un endroit complètement différent. Une fibre est une pile complète et indépendante que vous pouvez suspendre à un point arbitraire et poursuivre sans remonter la pile. C’est l’élément manquant qui permet aux bibliothèques de remplacer les chaînes de promesses par un await à l’apparence synchrone — à l’origine des API modernes de ReactPHP et d’Amp.

Votre première fibre

Créez une fibre avec une fonction de rappel, démarrez-la avec start() et laissez-la se suspendre avec suspend(). Le contrôle revient à l’appelant au point de suspension ; resume() reprend exactement à cet endroit.

<?php
$fiber = new Fiber(function (): void {
    echo "A: inside fiber\n";
    $received = Fiber::suspend('paused');
    echo "C: resumed with '$received'\n";
});

$value = $fiber->start();          // prints A, returns 'paused'
echo "B: fiber suspended, got '$value'\n";
$fiber->resume('hello');           // prints C
echo "D: fiber done\n";

Les quatre méthodes fondamentales

L’API est concise :

  • $fiber->start(...$args) — commence l’exécution ; renvoie la première valeur de suspension.
  • Fiber::suspend($value) — met en pause la fibre courante et remet $value à celui qui la reprend.
  • $fiber->resume($value) — poursuit l’exécution ; $value devient la valeur de retour de suspend().
  • $fiber->getReturn() — renvoie la valeur de retour de la fonction de rappel une fois la fibre terminée.

Les valeurs circulent dans les deux sens de part et d’autre de la frontière de suspension.

Transmission bidirectionnelle des valeurs

Une fibre peut envoyer une requête et recevoir une réponse en retour — c’est le cœur de la manière dont une boucle d’événements injecte les résultats d’E/S dans des tâches suspendues qui les attendent.

<?php
$fiber = new Fiber(function (): int {
    $a = Fiber::suspend('need first number');
    $b = Fiber::suspend('need second number');
    return $a + $b;
});

$fiber->start();        // suspends: 'need first number'
$fiber->resume(10);     // a = 10, suspends: 'need second number'
$fiber->resume(32);     // b = 32, fiber returns
echo $fiber->getReturn(), PHP_EOL; // 42

État et inspection des fibres

Vous pouvez interroger une fibre sur son cycle de vie. Appeler resume() sur une fibre terminée lève FiberError ; utilisez donc ces vérifications lors de la création d’un ordonnanceur.

<?php
$fiber = new Fiber(function () { Fiber::suspend(); });
var_dump($fiber->isStarted());     // false
$fiber->start();
var_dump($fiber->isStarted());     // true
var_dump($fiber->isSuspended());   // true
var_dump($fiber->isRunning());     // false (we're outside it)
$fiber->resume();
var_dump($fiber->isTerminated());  // true

Construire un petit ordonnanceur

Des Fibres associées à une file d’attente forment un ordonnanceur coopératif. Chaque tâche se suspend pour céder le contrôle ; l’ordonnanceur les exécute à tour de rôle jusqu’à ce qu’elles soient toutes terminées. C’est l’ossature de tout environnement d’exécution asynchrone.

<?php
$tasks = [];
foreach (['X', 'Y', 'Z'] as $name) {
    $tasks[] = new Fiber(function () use ($name) {
        for ($i = 1; $i <= 2; $i++) {
            echo "$name step $i\n";
            Fiber::suspend();   // give others a turn
        }
    });
}
foreach ($tasks as $t) { $t->start(); }
while ($tasks) {
    foreach ($tasks as $k => $t) {
        if ($t->isTerminated()) { unset($tasks[$k]); continue; }
        $t->resume();
    }
}

Exceptions entre les frontières

throwInto() (appelé throw() dans l’API sous la forme $fiber->throw()) injecte une exception au point de suspension — c’est ainsi qu’une boucle signale l’échec d’une opération d’E/S à la tâche qui l’attend. L’exception ressurgit exactement à l’endroit où la fibre était suspendue.

<?php
$fiber = new Fiber(function () {
    try {
        Fiber::suspend();
    } catch (RuntimeException $e) {
        echo 'caught: ' . $e->getMessage() . PHP_EOL;
    }
});
$fiber->start();
$fiber->throw(new RuntimeException('io failed')); // prints: caught: io failed

Fibres et générateurs

Les générateurs (yield) se suspendent également — mais uniquement dans la fonction au sommet. Pour attendre depuis une fonction auxiliaire imbriquée avec des générateurs, vous devez faire remonter yield from jusqu’au sommet de la pile, ce qui contamine chaque fonction. Les Fibres suspendent toute la pile depuis n’importe quel niveau ; un appel profondément imbriqué peut donc appeler Fiber::suspend() sans que ses appelants le sachent. C’est pourquoi await peut être un appel de fonction ordinaire plutôt qu’un yield.

<?php
function deep(): string {
    // No yield needed in the call chain — suspends the whole fiber
    return Fiber::suspend('awaiting from deep');
}
$f = new Fiber(fn() => print(deep() . PHP_EOL));
$f->start();
$f->resume('value injected at depth');

La restriction liée à la suspension

Une règle stricte s’applique : vous ne pouvez appeler Fiber::suspend() que depuis l’intérieur d’une fibre. Suspendre l’exécution depuis le fil principal ou au travers d’une fonction de rappel au niveau C qui ne prend pas en charge les fibres (certains anciens comparateurs de usort, certains rappels internes) lève FiberError: Cannot suspend outside of a fiber. Les bibliothèques masquent cette contrainte en veillant à ce que tout le code utilisateur s’exécute à l’intérieur d’une fibre pilotée par la boucle.

<?php
try {
    Fiber::suspend(); // main thread — illegal
} catch (FiberError $e) {
    echo $e->getMessage(), PHP_EOL; // Cannot suspend outside of a fiber
}

Comment les bibliothèques utilisent les fibres

Vous écrivez rarement des Fibres brutes dans le code d’une application. Des cadres comme Amp v3 et ReactPHP (via fibers) les encapsulent : await($promise) appelle en interne Fiber::suspend(), enregistre une suite auprès de la boucle d’événements, puis appelle resume() sur votre fibre lorsque les E/S sont terminées. Votre code a l’apparence d’un code synchrone ; l’environnement d’exécution gère la mise en attente et l’ordonnancement.

<?php
// Conceptual: what an await() helper does under the hood
function await(Promise $p): mixed {
    $fiber = Fiber::getCurrent() ?? throw new Error('await() outside fiber');
    $p->then(fn($v) => $fiber->resume($v),
             fn($e) => $fiber->throw($e));
    return Fiber::suspend(); // parked until the promise settles
}

Mémoire et précautions liées au cycle de vie

Chaque fibre alloue sa propre pile ; en créer plusieurs centaines de milliers a donc un coût mémoire, même si elles sont bien moins lourdes que les fils d’exécution de l’OS. Une fibre suspendue indéfiniment n’est jamais récupérée par le ramasse-miettes si quelque chose la référence encore — une fuite subtile dans les serveurs de longue durée. De plus, une exception non interceptée levée par la fonction de rappel d’une fibre se propage hors de l’appel resume()/start() ; l’ordonnanceur doit donc encapsuler les reprises dans une gestion des exceptions.

<?php
$fiber = new Fiber(function () {
    throw new RuntimeException('boom inside fiber');
});
try {
    $fiber->start(); // exception surfaces here, at the resumer
} catch (RuntimeException $e) {
    echo 'scheduler caught: ' . $e->getMessage() . PHP_EOL;
}

Vérification rapide

Quel avantage clé les Fibres offrent-elles par rapport aux générateurs pour l’asynchrone ?

Récapitulatif

Les Fibres sont la primitive de concurrence de bas niveau de PHP :

  • start(), Fiber::suspend(), resume() et getReturn() mettent en pause et poursuivent une pile d’appels complète, en transmettant des valeurs dans les deux sens.
  • Les méthodes d’état (isSuspended, isTerminated) et throw() permettent de créer un ordonnanceur coopératif et d’injecter des erreurs d’E/S.
  • Contrairement aux générateurs, une fibre peut se suspendre à n’importe quel niveau, ce qui permet un await() transparent.
  • Vous ne pouvez suspendre l’exécution que depuis l’intérieur d’une fibre ; des cadres comme Amp et ReactPHP encapsulent les fibres afin que votre code asynchrone se lise comme du code synchrone.

Questions Fréquemment Posées

La leçon « Fibers de PHP 8.1 » est-elle gratuite ?

Oui — le texte complet de « Fibers de PHP 8.1 » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours PHP Academy, passe à CoddyKit PRO. Le cours PHP Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Fibers de PHP 8.1 » ?

Mettez en pause et reprenez l’exécution avec les Fibers natives. Tu pratiques PHP Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer PHP Academy ?

Aucune expérience préalable n'est requise. PHP Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Fibers de PHP 8.1 » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon PHP Academy ?

Oui. Chaque leçon PHP Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Modèle de concurrence de PHP
  2. Fibers de PHP 8.1
  3. Boucles d’événements avec ReactPHP
  4. Serveurs hautes performances avec Swoole
← Retour à PHP Academy