2016-01-03 11 views
22

Il PHP 7 Backward-Incompatible Changes Document dice il seguente su foreach:PHP 7 modifiche a foreach: Posso ancora eliminare elementi in loro matrice su cui sto iterando?

Quando utilizzato nella modalità per valore predefinito, foreach sarà ora operare su una copia della matrice essendo iterato piuttosto che la matrice stessa. Ciò significa che le modifiche apportate alla matrice durante l'iterazione non influiranno sui valori iterati.

Sto cercando di capire cosa significa e la mia domanda principale è se questo codice funzionerà allo stesso modo in PHP 7 come in PHP 5.6?

foreach($array as $elementKey => $element) { 
    if ($element == 'x') { 
     unset($array[$elementKey]); 
    } 
} 

Le mie due domande sono:

  1. Sarà questo codice ancora lavorare?

  2. Se sì, puoi spiegare (forse con l'esempio) cosa significa questo nuovo cambiamento in PHP 7?

Modifica

Sto rileggendo la dichiarazione doc. Sto pensando che ciò che significa è che, se cambi i valori degli elementi più in basso nell'array, quelle modifiche non saranno lì quando arrivi a quegli elementi nell'iterazione. Esempio:

$array = ['x', 'y', 'z']; 

$new = []; 

foreach($array as $element) { 
    if ($element == 'x') { 
     $array[2] = 'a'; 
    } 

    $new[] = $element; 
} 

print_r($new); 

Tuttavia, quando ho run this example non sembra mostrare alcuna differenza nelle versioni di PHP (anche se non ho mai usato questo strumento prima, quindi non sono sicuro di come funziona).

Mi rendo conto che se lo faccio per riferimento, riceverò uno a nuovo. Altrimenti non lo farò. Ma questo sembra essere il caso in entrambe le versioni.

Quello che ho davvero bisogno di sapere è qual è l'incompatibilità (ad esempio)?

Edit 2

Il answer link suggested dal @NikiC fornisce il resto della storia che stavo cercando:

Nella maggior parte dei casi questo cambiamento è trasparente e non ha altro effetto che una migliore performance . Tuttavia v'è un'occasione se si traduce in un comportamento diverso, cioè il caso in cui la matrice di un riferimento in anticipo:

$array = [1, 2, 3, 4, 5]; 
$ref = &$array; 
foreach ($array as $val) { 
    var_dump($val); 
    $array[2] = 0; 
} 
/* Old output: 1, 2, 0, 4, 5 */ 
/* New output: 1, 2, 3, 4, 5 */ 

precedenza per valore iterazione di riferimento-array era casi speciali. In questo caso non si è verificata alcuna duplicazione, quindi tutte le modifiche dell'array durante l'iterazione verranno riflesse dal loop. In PHP 7 questo caso speciale è scomparso: l'iterazione in valore nominale di un array continuerà a funzionare sugli elementi originali, ignorando eventuali modifiche durante il ciclo.

Questa risposta spiega il "caso speciale" raro in cui funzionano le cose diverse tra le versioni a riguardo foreach opera su una copia della matrice.

risposta

19

Tutto ciò significa che ora devi dire esplicitamente di voler fare riferimento all'array che stai iterando ora.

Nel codice di esempio, tuttavia, si fa comunque riferimento all'array di root in modo che funzioni indipendentemente dal fatto che si passi o meno per riferimento.

<?php 
$array = ['x', 'y', 'z']; 

foreach($array as $elementKey => $element) { 
    if ($element=='x') { 
     unset($array[$elementKey]); 
    } 
} 

var_dump($array); // lists 'y' and 'z' 

Un esempio migliore. In questo caso, stiamo modificando il valore all'interno dello foreach senza un riferimento. Come tale, verranno perse le modifiche locali:

<?php 
$array = ['x', 'y', 'z']; 

foreach($array as $element) { 
    if ($element=='x') { 
     $element = 'a'; 
    } 
} 

var_dump($array); // 'x', 'y', 'z' 

Vs per riferimento, in cui si dichiara la $element per essere un riferimento all'elemento dell'array:

<?php 
$array = ['x', 'y', 'z']; 

foreach($array as &$element) { 
    if ($element=='x') { 
     $element = 'a'; 
    } 
} 

var_dump($array); // 'a', 'y', 'z' 

Here's a demo of this code running sulle varie versioni di PHP.

+0

Grazie Machavity. I tuoi esempi sono utili e hanno senso per me. Mi chiedo ancora quale sia la differenza tra 5.6 e 7. Mi sembra che tutti e tre di questi esempi stiano facendo quello che mi aspetterei in PHP 5.6 – userlite

+2

In effetti, tutti e tre gli esempi qui si comportano allo stesso modo in 5 e 7. – rjdown

+0

I penso che la preoccupazione principale per cui sono venuto qui sia stata risolta, ovvero che volevo essere sicuro che il concetto di disinserimento degli elementi nell'array su cui sto iterando non sarebbe diverso in PHP 7. La mia preoccupazione secondaria è solo comprendendo ciò che in realtà è diverso. La maggior parte delle altre incompatibilità hanno esempi nel doc, ma questo no. – userlite

Problemi correlati