Ce face yield
O funcție care conține yield nu rulează imediat. Apelul ei returnează un obiect Generator, pe care îl parcurgi cu foreach. La fiecare pas, funcția rulează până la următorul yield, dă valoarea și se „pune pe pauză” până la pasul următor.
Avantajul este memoria: poți parcurge un fișier de un milion de linii sau rezultatele unei interogări mari fără să le încarci pe toate într-un tablou. Cu yield $cheie => $valoare dai și chei, iar yield from preia valorile din alt generator sau tablou.
Dacă ai nevoie de un tablou obișnuit din generator, folosește iterator_to_array().
Exemple
Exemplul 1: Valori produse pe rând
Observă ordinea mesajelor: funcția rulează doar când foreach cere următoarea valoare.
<?php
function numere(int $pana): Generator
{
for ($i = 1; $i <= $pana; $i++) {
echo "(generez $i) ";
yield $i;
}
}
foreach (numere(3) as $n) {
echo "primesc $n\n";
}
Rezultat
(generez 1) primesc 1
(generez 2) primesc 2
(generez 3) primesc 3
Exemplul 2: Citirea unui fișier linie cu linie
<?php
file_put_contents("comenzi.csv", "1024,Ana,259.90\n1025,Mihai,80.00\n1026,Ioana,1299.50\n");
function linii(string $fisier): Generator
{
$f = fopen($fisier, "r");
while (($linie = fgets($f)) !== false) {
yield str_getcsv(trim($linie), ",", '"', "");
}
fclose($f);
}
foreach (linii("comenzi.csv") as [$id, $client, $total]) {
echo "Comanda $id: $client, $total lei\n";
}
Rezultat
Comanda 1024: Ana, 259.90 lei
Comanda 1025: Mihai, 80.00 lei
Comanda 1026: Ioana, 1299.50 lei
Exemplul 3: Chei, yield from și iterator_to_array
<?php
function capitale(): Generator
{
yield "RO" => "București";
yield "MD" => "Chișinău";
yield from ["HU" => "Budapesta"];
}
print_r(iterator_to_array(capitale()));
Rezultat
Array
(
[RO] => București
[MD] => Chișinău
[HU] => Budapesta
)
Greșeli frecvente
- Încerci să parcurgi același generator de două ori. Un generator poate fi parcurs o singură dată; apelează din nou funcția pentru o parcurgere nouă.
- Folosești
count()pe un generator. Nu funcționează (TypeError); foloseșteiterator_count(), care însă parcurge tot generatorul.