2017-04-20 2 views
0

ich ein Stück PHP-Code haben, wie folgt:Ändern Array-Werte in PHP-Speicher Auspuff

foreach($collection as $key => $item) { 
    $collection[$key]['column'] = 'test'; 
    $item['column'] = 'test'; 
} 

Wenn die Sammelanordnung mehr als 30.000 Zeilen hat, erhalte ich diesen Fehler PHP Fatal error: Erlaubt Speichergröße von 134.217.728 Bytes erschöpft (versucht, 89 Bytes zuzuordnen).

Wenn ich die Zeile $ collection [$ key] ['column'] entferne, kann der Forloop erfolgreich abgeschlossen werden.

Was ich nicht verstehen kann, ist das nicht Linie 2 und Linie 3 im Grunde gleich? Sie ändern beide dasselbe Element im $ collection-Array.

Was fehlt mir hier?

+1

Eigentlich würde das Ändern von $ item eine Kopie erstellen und diese ändern, nicht die $ collection (siehe copy-on-write). Also wahrscheinlich ist php Müll sammeln jene $ Element, die nicht verwendet werden, so dass es nicht erschöpft Ihren Speicher im Gegensatz zu Hinzufügen zur Sammlung wie in Zeile 2. Ich vermute, wenn Sie $ -Eintrag zu $ ​​ändern $ -Eintrag (verursacht Änderungen an $ Artikel, um $ Sammlung zu ändern) in Zeile 1 hätten Sie das gleiche Problem beim Auskommentieren von Zeile 2. – Christopher

Antwort

0

Um Ihre Frage zu beantworten, lassen Sie uns auf der foreach docs

On each iteration, the value of the current element is assigned to $value and the internal array pointer is advanced by one (so on the next iteration, you'll be looking at the next element).

Lassen Sie uns zunächst einen kurzen Blick zuerst Ihre erste Frage intensivieren und lassen Sie uns Ihre zweite Frage nehmen.

What I cannot understand is that aren't line 2 and line 3 basically the same?

Eigentlich sind sie nicht gleich sind, nehmen diese kurze Beispiele:

$array = ['a', 'a', 'a', 'a']; 

foreach ($array as $key => $value) { 
    $value = 'b'; 
} 

print_r($array); 
// Output : Array ([0] => a [1] => a [2] => a [3] => a) 

während im zweiten Fall:

$array = ['a', 'a', 'a', 'a']; 

foreach ($array as $key => $value) { 
    $array[$key] = 'b'; 
} 

print_r($array); 
// Output : Array ([0] => b [1] => b [2] => b [3] => b) 

so, es, dass in Ihrem ersten Fall völlig klar ist, Sie hatten sozusagen einen Kopierwert oder einen zugewiesenen Wert geändert und den tatsächlichen Wert nicht berührt.

so können wir sagen, dass -so foreach als PHP-Funktionen speak- seinen eigenen Kontext hat, zum Beispiel:

foreach ($array as $key => $value) { 
    // $value variable will be only visible here 
    // within the foreach context 
} 
echo $value; // will output Undefined variable 

They are both changing the same item in the $collection array.

man sagen kann - oder annehmen -, dass Sie bestanden haben eine Variable nach foreach nach Wert, so php - wie in foreach docs erwähnt - hatte eine Kopie von Ihrem Array-Element, nicht den tatsächlichen Wert geändert.

während im zweiten Beispiel haben Sie den realen Wert des Arrays $array nicht nur eine Kopie davon geändert.

in meinen Beispielen Zusammenhang Ihr Array in dem Ort zu ändern, müssen Sie Ihre Variable übergeben by reference foreach Lage sein, Ihren Array-Wert direkt zum Beispiel bearbeiten:

$array = ['a', 'a', 'a', 'a']; 

foreach ($array as $key => &$value) { 
//      ^
    $value = 'b'; 
} 

print_r($array); 
// Output : Array ([0] => b [1] => b [2] => b [3] => b) 

lassen Sie uns auf Ihre andere Frage bewegen:

If I remove the line $collection[$key]['column'], the forloop can finish successfully.

dies liegt daran, dass, wie oben erwähnt der Fall ist, sind vorbei Sie Ihre Variable von Wert foreach, so dass für jede Iteration ove r Ihre 30,000 Array gibt es drei Operationen php durchführen wird: -

1) an einen anderen Ort jedes Element Ihres Arrays kopieren in Ihrem Gedächtnis
2) aktualisieren Sie diese kopierte Element
3) aktualisieren Sie Ihre Sammlung Array

was ich denke, nimmt mehr Speicher als Ihre maximale Speichergrenze.

so, wie Christopher in seinem Kommentar erwähnt und wie in foreach doc page erwähnt:

In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.

Ihren Wert als Verweis kann die Speichernutzung des Skripts reduzieren.

0

Versuchen Sie dies mit:

ini_set('memory_limit', '-1'); 

Dies wird nicht vorgeschlagen werden getan, aber in Ihnen falls es erforderlich ist. Dies überschreibt das Standard-PHP-Speicherlimit.

+1

Die OP-Frage war über die Unterschiede in der Zuordnung, dass man das Speicherproblem und nicht das andere, anstatt das Speicherproblem zu vermeiden insgesamt ... – Christopher

+0

Aber der Titel besagt, dass das Gedächtnis erschöpft ist. –

+0

Es gibt ein Speicherleck und um zu wissen, warum die Person den gesamten Code veröffentlichen muss. –