2016-06-15 28 views
7

Ieri, ho imparato che PHP ha un metodo yield(). Non ero sicuro della sua utilità in PHP.rendimento PHP vs recupero PDO?

Un collega ha detto che potrebbe aiutare per le istruzioni SQL che tornano molte righe causando potenziali problemi di memoria. Credo che si riferisse a fetchAll(). Ma, invece di usare fetchAll(), si può anche usare fetch() e di processo righe uno per uno. Quindi, yield() non è la chiave per risolvere il problema a cui si riferisce.

mi sto perdendo qualcosa su yield() vs fetch() qui? Ci sono più vantaggi nell'uso di yield() e generatori?

P.S .: E 'vero che è più facile scrivere codice pulito, leggibile e maitainable in grandi applicazioni con yield() che con con fetch().

+3

Beh, DOP non è un ottimo esempio per la resa usefilness, perché DOP la dichiarazione già implementa un'interfaccia percorribile e può essere ripetuta usando foreach. Ma con mysqli puoi usare yield per rendere il risultato mysqli ripetuto con foreach. –

+1

Bene, in generale ciò si riduce a ciò che * i generatori * sono utili (poiché 'yield' è un dettaglio di implementazione dei generatori). E i generatori sono utili per creare qualcosa che si comporta come un array (o piuttosto un * iterable *), ma non memorizza tutti i suoi dati in memoria ma * lo genera * con ogni iterazione secondo necessità. Sì, questo può essere usato nel contesto del recupero dei risultati del database, ma potrebbe anche essere usato per implementare un contatore infinito o un numero qualsiasi di altre cose. – deceze

risposta

9

Quindi yield() non è la chiave per risolvere il problema a cui si riferisce.

Esattamente

.

Ma può farti mascherare la sequenza while()/fetch() come una chiamata foreach() se preferisci, senza sovraccarico di memoria pure.

Tuttavia, DOP non è un buon esempio, perché PDOStatement implementa già un'interfaccia attraversabile e quindi can be iterated over using foreach():

$stmt = $pdo->query('SELECT name FROM users'); 
foreach ($stmt as $row) 
{ 
    var_export($row); 
} 

Così diamo mysqli per l'esempio API che può solo flusso di risultati uno per uno.
Modifica. In realtà, anche since 5.4.0 mysqli supports Traversable, quindi non c'è motivo di usare yield con mysqli_result. Ma io me lo tengo per lo scopo dimostrativo.

Creiamo un generatore di come questo

function mysqli_gen (mysqli_result $res) 
{ 
    while($row = mysqli_fetch_assoc($res)) 
    { 
     yield $row; 
    } 
} 

e ora è possibile ottenere righe utilizzando foreach senza un overhead:

$res = $mysqli->query("SELECT * FROM users"); 
foreach (mysqli_gen($res) as $row) 
{ 
    var_export($row); 
}