W3docs

yield

Le mot-clé yield permet de créer des fonctions génératrices en PHP qui produisent des valeurs une à une, économisant la mémoire.

Introduction

Le mot-clé yield transforme une fonction PHP ordinaire en générateur — une fonction qui produit une séquence de valeurs une à une, se mettant en pause après chaque valeur et reprenant là où elle s'est arrêtée lorsque la valeur suivante est demandée. Cette page explique le fonctionnement de yield, comment produire des clés, comment envoyer des valeurs dans un générateur, la syntaxe de délégation yield from, et dans quels cas les générateurs économisent de la mémoire par rapport à la construction d'un tableau complet.

Une fonction devient un générateur dès qu'elle contient au moins un yield. L'appeler ne pas exécute le corps — elle retourne un objet Generator. Le corps s'exécute uniquement lors de l'itération, avançant jusqu'au prochain yield à chaque étape. Comme un générateur implémente l'interface Iterator, on le consomme généralement avec une boucle foreach.

Un premier générateur

Chaque yield remet une valeur à l'appelant et gèle la fonction jusqu'à ce que la valeur suivante soit demandée.

php— editable, runs on the server

myGenerator() retourne un objet générateur au lieu de s'exécuter immédiatement. La boucle foreach en extrait les valeurs : à chaque passage, la fonction s'exécute jusqu'au prochain yield, émet cette valeur, puis se met en pause. La sortie est :

Hello World !

Contrairement à une fonction qui construit et returne un tableau, les trois chaînes de caractères ne sont jamais toutes conservées en mémoire en même temps — chacune est produite à la demande. Comparez cela avec la façon dont une fonction normale utilise return pour renvoyer une seule valeur et se terminer.

Produire des clés

Un générateur peut produire des paires clé/valeur avec la syntaxe yield $key => $value, exactement comme un tableau associatif. Les clés sont disponibles dans foreach :

<?php

function settings()
{
  yield "host" => "localhost";
  yield "port" => 5432;
  yield "user" => "admin";
}

foreach (settings() as $key => $value) {
  echo "$key = $value\n";
}

Sortie :

host = localhost
port = 5432
user = admin

Si vous ne fournissez pas de clés, PHP numérote automatiquement les valeurs produites à partir de 0, tout comme un tableau indexé.

Les générateurs sont paresseux : une plage économe en mémoire

Le véritable avantage de yield est que les valeurs sont calculées uniquement lorsque nécessaire. Un générateur qui produit un million de nombres utilise une mémoire constante, tandis qu'un tableau d'un million de nombres les alloue tous d'avance.

<?php

function gen_range($start, $end)
{
  for ($i = $start; $i <= $end; $i++) {
    yield $i;
  }
}

$sum = 0;
foreach (gen_range(1, 1000000) as $n) {
  $sum += $n;
}

echo $sum;

Sortie :

500000500000

La boucle ne construit jamais un tableau [1, 2, …, 1000000] ; seul un entier existe à la fois. C'est le modèle à adopter lors de la lecture de fichiers volumineux ligne par ligne ou de la diffusion en continu de lignes de base de données.

Retourner une valeur depuis un générateur

Un générateur peut également utiliser return pour exposer une valeur finale (PHP 7+). La valeur de retour ne fait pas partie de l'itération — vous la lisez ensuite avec getReturn() :

<?php

function counter()
{
  yield 1;
  yield 2;
  return "done";
}

$gen = counter();
foreach ($gen as $value) {
  echo $value . " ";
}
echo $gen->getReturn();

Sortie :

1 2 done

Appeler getReturn() avant que le générateur n'ait fini d'itérer lève une exception, donc épuisez-le toujours en premier.

Envoyer des valeurs avec send()

Les générateurs sont bidirectionnels : une expression yield peut également recevoir une valeur envoyée par l'appelant via send(). C'est la base des coroutines.

<?php

function echoTimes()
{
  while (true) {
    $received = yield;
    echo "Got: $received\n";
  }
}

$gen = echoTimes();
$gen->current();      // prime the generator (run up to the first yield)
$gen->send("a");
$gen->send("b");

Sortie :

Got: a
Got: b

send($value) reprend le générateur, faisant en sorte que l'expression yield en pause s'évalue à $value, puis s'exécute jusqu'au prochain yield.

Déléguer avec yield from

yield from (PHP 7+) produit chaque valeur d'un autre générateur, tableau ou Traversable, les aplatissant dans le générateur courant sans boucle manuelle :

<?php

function inner()
{
  yield 2;
  yield 3;
}

function outer()
{
  yield 1;
  yield from inner();
  yield from [4, 5];
}

foreach (outer() as $value) {
  echo $value . " ";
}

Sortie :

1 2 3 4 5 

Quand utiliser un générateur

  • Séquences larges ou non bornées — lire un fichier de plusieurs gigaoctets ou un flux infini où il est impossible de tout contenir dans un tableau.
  • Valeurs coûteuses dont vous pourriez ne pas avoir besoin — si le consommateur peut s'arrêter tôt (break), un générateur évite de calculer le reste.
  • Code d'itération plus propre — remplacer une classe Iterator personnalisée par une simple fonction.

Évitez les générateurs lorsque vous avez besoin d'un accès aléatoire ($arr[42]), de count() les résultats à moindre coût, ou d'itérer plusieurs fois sur les mêmes données — un générateur ne peut être parcouru qu'une seule fois. Pour ces cas, construisez un tableau normal, éventuellement avec des fonctions PHP comme array_map.

Pratique

Pratique
Quelle est la fonction du mot-clé 'yield' en PHP ?
Quelle est la fonction du mot-clé 'yield' en PHP ?
Was this page helpful?