Fibers di PHP 8.1
Sospendete e riprendete l'esecuzione con le Fibers native.
Fibers di PHP 8.1 è una lezione PHP Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento PHP Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso PHP Academy include 4 lezioni in totale.
Cosa offrono le Fibers
PHP 8.1 ha aggiunto le Fibers: una primitiva integrata nel core che consente di sospendere uno stack di chiamate in esecuzione e di riprenderlo in seguito, da un punto completamente diverso. Una Fiber è uno stack completo e indipendente che può essere sospeso in un punto arbitrario e ripreso senza fare unwinding. È il tassello mancante che consente alle librerie di sostituire le catene di promise con un await dall'aspetto sincrono — il meccanismo alla base delle API moderne di ReactPHP e Amp.
La prima Fiber
Crei una Fiber con un callback, la avvii con start() e lasci che si sospenda con suspend(). Il controllo torna al chiamante nel punto di sospensione; resume() riprende l'esecuzione esattamente da lì.
<?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";I quattro metodi fondamentali
L'API è essenziale:
$fiber->start(...$args)— avvia l'esecuzione e restituisce il primo valore della sospensione.Fiber::suspend($value)— sospende la Fiber corrente, consegnando$valuea chi la riprende.$fiber->resume($value)— riprende l'esecuzione;$valuediventa il valore restituito dasuspend().$fiber->getReturn()— restituisce il valore restituito dal callback una volta terminato.
I valori fluiscono in entrambe le direzioni attraverso il confine di sospensione.
Passaggio bidirezionale dei valori
Una Fiber può inviare una richiesta e ricevere in risposta un risultato: è il cuore del modo in cui un event loop immette i risultati I/O nelle attività sospese.
<?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; // 42Stato e introspezione delle Fiber
Può interrogare una Fiber sul suo ciclo di vita. Chiamare resume() su una Fiber terminata genera FiberError, quindi, quando costruisce uno scheduler, utilizzi questi controlli.
<?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()); // trueCreare un piccolo scheduler
Una Fiber e una coda equivalgono a uno scheduler cooperativo. Ogni attività si sospende per cedere il controllo; lo scheduler esegue le attività a turno finché non sono terminate tutte. Questo è lo scheletro interno di ogni runtime asincrono.
<?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();
}
}Eccezioni oltre i confini
throwInto() (chiamato throw() nell'API come $fiber->throw()) inietta un'eccezione nel punto di sospensione: è il modo in cui un loop segnala un'operazione I/O non riuscita all'attività in attesa. L'eccezione riemerge esattamente nel punto in cui la Fiber era stata sospesa.
<?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 failedFibers e generatori a confronto
I generatori (yield) si sospendono anch'essi, ma solo la funzione in cima. Per attendere da un helper annidato con i generatori, deve usare yield from lungo tutto lo stack, modificando ogni funzione della catena. Le Fibers sospendono l'intero stack da qualsiasi profondità, quindi una chiamata profondamente annidata può eseguire Fiber::suspend() senza che i chiamanti ne siano a conoscenza. Per questo await può essere una normale chiamata di funzione anziché 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');Il vincolo della sospensione
Una regola inderogabile: è possibile eseguire Fiber::suspend() solo dall'interno di una Fiber. Sospendere dal thread principale o attraverso un callback a livello C che non supporta le Fiber (alcuni comparatori legacy di usort, determinati callback interni) genera FiberError: Cannot suspend outside of a fiber. Le librerie nascondono questo dettaglio assicurandosi che tutto il codice dell'utente venga eseguito all'interno di una Fiber gestita dal loop.
<?php
try {
Fiber::suspend(); // main thread — illegal
} catch (FiberError $e) {
echo $e->getMessage(), PHP_EOL; // Cannot suspend outside of a fiber
}Come le librerie usano le Fibers
Di rado scriverà Fiber grezze nel codice dell'applicazione. Framework come Amp v3 e ReactPHP (via fibers) le racchiudono: await($promise) richiama internamente Fiber::suspend(), registra una continuazione nell'event loop e richiama resume() sulla Sua Fiber quando l'I/O è completato. Il Suo codice appare sincrono; il runtime gestisce la sospensione e la pianificazione.
<?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
}Considerazioni su memoria e ciclo di vita
Ogni Fiber alloca il proprio stack, quindi crearne centinaia di migliaia ha un costo in memoria (anche se molto inferiore a quello dei thread del sistema operativo). Una Fiber sospesa per sempre non viene mai raccolta dal garbage collector se qualcosa continua a mantenerne un riferimento: una perdita difficile da individuare nei server a esecuzione prolungata. Inoltre, se il callback di una Fiber genera un'eccezione non intercettata, questa si propaga fuori dalla chiamata resume()/start(); pertanto lo scheduler deve racchiudere le riprese in un blocco try/catch.
<?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;
}Verifica rapida
Qual è il vantaggio fondamentale delle Fibers rispetto ai generatori per la programmazione asincrona?
Riepilogo
Le Fibers sono la primitiva di basso livello per la concorrenza di PHP:
start(),Fiber::suspend(),resume()egetReturn()sospendono e riprendono un intero stack di chiamate, passando valori in entrambe le direzioni.- I metodi per lo stato (
isSuspended,isTerminated) ethrow()consentono di creare uno scheduler cooperativo e di iniettare errori I/O. - A differenza dei generatori, una Fiber si sospende a qualsiasi profondità, consentendo un
await()trasparente. - È possibile sospendere solo all'interno di una Fiber; framework come Amp e ReactPHP racchiudono le Fiber, così il codice asincrono appare sincrono.
Domande Frequenti
La lezione «Fibers di PHP 8.1» è gratuita?
Sì — il testo completo di «Fibers di PHP 8.1» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso PHP Academy, passa a CoddyKit PRO. Il corso PHP Academy include 4 lezioni in totale.
Cosa imparerò in «Fibers di PHP 8.1»?
Sospendete e riprendete l'esecuzione con le Fibers native. Eserciti PHP Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare PHP Academy?
Non è richiesta alcuna esperienza precedente. PHP Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Fibers di PHP 8.1»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione PHP Academy?
Sì. Ogni lezione PHP Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Il modello di concorrenza di PHP
- Fibers di PHP 8.1
- Event loop con ReactPHP
- Server ad alte prestazioni con Swoole