yield în PHP

Funcții și apeluri PHP 5.5+ (yield from: PHP 7.0+)

Transformă o funcție într-un generator, care produce valorile pe rând, doar când sunt cerute.

Sintaxă
function nume() { yield valoare; yield cheie => valoare; }

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ște iterator_count(), care însă parcurge tot generatorul.

Comenzi înrudite

  • foreach: Parcurge, pe rând, fiecare element dintr-un tablou.
  • return: Oprește funcția și trimite înapoi o valoare către codul care a apelat-o.
  • function: Definește o funcție proprie: un bloc de cod cu nume, pe care îl poți apela de oricâte ori.