PHP foreach ändert die ursprünglichen Array-Werte

143

Ich bin sehr neu in mehrdimensionalen Arrays, und das nervt mich sehr.

Mein Array ist wie folgt:

$fields = array(
    "names" => array(
         "type"         => "text",
         "class"        => "name",
         "name"         => "name",
         "text_before"  => "name",
         "value"        => "",
         "required"     => true,
    )
)

Dann habe ich eine Funktion bekommen, die prüft, ob diese Eingaben ausgefüllt sind, wenn sie benötigt werden.

function checkForm($fields){
    foreach($fields as $field){
        if($field['required'] && strlen($_POST[$field['name']]) <= 0){
            $fields[$field]['value'] = "Some error";
        }
    }
    return $fields;
}

Jetzt ist mein Problem diese Linie

$fields[$field]['value'] = "Some error";

Ich möchte den Inhalt des ursprünglichen Arrays ändern, da ich dies zurückgebe, aber wie erhalte ich den Namen des aktuellen Arrays (Namen in diesem Beispiel) in meiner foreach-Schleife?

Jeppe
quelle
1
Mögliches Duplikat von PHP - Ändern Sie das aktuelle Objekt in jeder Schleife
PhoneixS
1
Egal wie neu Sie sind (oder früher waren) - dies können Sie aus der PHP-Dokumentation lesen: php.net/manual/en/control-structures.foreach.php
Nikolay Ivanov

Antworten:

261

In PHP ist das Übergeben von reference ( &) ... umstritten. Ich empfehle, es nicht zu verwenden, es sei denn, Sie wissen, warum Sie es benötigen, und testen die Ergebnisse.

Ich würde Folgendes empfehlen:

foreach ($fields as $key => $field) {
    if ($field['required'] && strlen($_POST[$field['name']]) <= 0) {
        $fields[$key]['value'] = "Some error";
    }
}

Verwenden $fieldSie es also grundsätzlich, wenn Sie die Werte benötigen und $fields[$key]wenn Sie die Daten ändern müssen.

Vlad Preda
quelle
Schön, das funktioniert! Ich habe so etwas zuerst versucht, aber ich glaube, ich habe es irgendwo vermasselt :) Jetzt werde ich dein Beispiel tausendmal verwenden und nie vergessen! :)
Jeppe
Ich bin froh, dass es geholfen hat. Außerdem empfehle ich, den Artikel zu lesen, den ich verlinkt habe, sowie die offizielle Dokumentation für foreach ( php.net/manual/ro/control-structures.foreach.php )
Vlad Preda
4
Fazit: Wenn Sie das Array / die Variable ändern möchten, sollten Sie eine Referenz verwenden. Es ist schneller, sauberer und besser lesbar.
Lulu
2
Ich bin gespannt, warum das Übergeben von Referenzen in a foreachkontrovers sein sollte. Es ist nicht so, als wäre es ein Funktionsaufruf mit versteckten Nebenwirkungen oder so.
UncaAlby
1
Vielen Dank, dass Sie gesagt haben, dass "Übergeben durch Referenz (&) ... umstritten ist", anstatt "Nicht durch Referenz übergeben" oder "Übergeben durch Referenz ist böse". Es ist weniger wahrscheinlich, dass ein Flammenkrieg beginnt. :)
Sean the Bean
162

Verwendung &:

foreach($arr as &$value)
{
     $value = $newVal;
}

&Übergibt einen Wert des Arrays als Referenz und erstellt keine neue Instanz der Variablen. Wenn Sie also die Referenz ändern, ändert sich der ursprüngliche Wert.

http://php.net/manual/en/language.references.pass.php

Edit 2018
Diese Antwort scheint von vielen Leuten im Internet favorisiert zu werden, weshalb ich beschlossen habe, weitere Informationen und vorsichtige Worte hinzuzufügen.
Während das Übergeben von Referenzen in foreach(oder Funktionen) eine saubere und kurze Lösung ist, kann dies für viele Anfänger eine gefährliche Gefahr sein.

  1. Schleifen in PHP haben keinen eigenen Bereich. - @ Mark Amery

    Dies kann ein ernstes Problem sein, wenn die Variablen im selben Bereich wiederverwendet werden. Eine andere SO-Frage zeigt deutlich, warum dies ein Problem sein könnte.

  2. Da foreach auf den internen Array-Zeiger in PHP 5 angewiesen ist, kann das Ändern innerhalb der Schleife zu unerwartetem Verhalten führen. - PHP-Dokumente für foreach

    Das Deaktivieren eines Datensatzes oder das Ändern des Hashwerts (des Schlüssels) während der Iteration in derselben Schleife kann zu möglicherweise unerwarteten Verhaltensweisen in PHP <7 führen. Das Problem wird noch komplizierter, wenn das Array selbst eine Referenz ist.

  3. Für jede Leistung.
    Im Allgemeinen bevorzugt PHP aufgrund der Copy-on-Write-Funktion die Wertübergabe. Dies bedeutet, dass PHP intern keine doppelten Daten erstellt, es sei denn, die Kopie muss geändert werden. Es ist fraglich, ob eine Referenzübergabe foreacheine Leistungsverbesserung bieten würde. Wie immer müssen Sie Ihr spezifisches Szenario testen und feststellen, welche Option weniger Speicher und CPU-Zeit benötigt. Weitere Informationen finden Sie in dem unten von NikiC verlinkten SO-Beitrag.

  4. Lesbarkeit des Codes.
    Das Erstellen von Referenzen in PHP gerät schnell außer Kontrolle. Wenn Sie ein Anfänger sind und nicht die volle Kontrolle darüber haben, was Sie tun, ist es am besten, sich von Referenzen fernzuhalten. Weitere Informationen zum &Operator finden Sie in diesem Handbuch: Referenz - Was bedeutet dieses Symbol in PHP?
    Für diejenigen, die mehr über diesen Teil der PHP-Sprache erfahren möchten: Erklärte PHP-Referenzen

Eine sehr schöne technische Erklärung von @NikiC zur internen Logik von PHP foreach-Schleifen:
Wie funktioniert PHP 'foreach' tatsächlich?

Dharman
quelle
Abgesehen von den aufgeführten Problemen empfehle ich, unset($value);nach der foreachschließenden Klammer hinzuzufügen , um sicherzustellen, dass die Referenzvariable nach der Iteration nicht mehr verfügbar ist. 3v4l.org/2V2AQ
fyrye
15

Verwenden foreach($fields as &$field){Sie diese Option, damit Sie mit dem ursprünglichen Array arbeiten können.

Hier erfahren Sie mehr über das Übergeben als Referenz.

k102
quelle
@RBA pls beziehen sich auf die Antworten oben - sie haben viel mehr Details und Updates - Ich habe PHP für eine Weile nicht mehr verwendet, so keine Updates zu diesem
k102
1
function checkForm(& $fields){
    foreach($fields as $field){
        if($field['required'] && strlen($_POST[$field['name']]) <= 0){
            $fields[$field]['value'] = "Some error";
        }
    }
    return $fields;
}

Dies ist, was ich vorschlagen würde, als Referenz zu übergeben

Sagar Kadam
quelle
Diese Technik wird verwendet, um den Wert der ursprünglichen Variablen zu ändern. da PHP die Pass by Value-Technik unterstützt. Wir müssen das Zeichen '&' vor der Variablen hinzufügen, um den Wert anzugeben, der als Referenz übergeben werden soll
Sagar Kadam
1
Warum dann immer noch zurückkehren $fields?
MAZux
Dies ist die schlechteste Antwort der 3 vorgeschlagenen. Wenn Sie auf diese Antwort stoßen, gestalten Sie Ihre Funktionen bitte nicht so, dass die vorhandenen Daten geändert und zurückgegeben werden. Für den ursprünglichen Autor: Sie haben keine Erklärung geliefert, warum diese Lösung besser wäre als die anderen oder wie sie überhaupt funktioniert.
Dharman
-6

Versuche dies

function checkForm($fields){
        foreach($fields as $field){
            if($field['required'] && strlen($_POST[$field['name']]) <= 0){
                $field['value'] = "Some error";
            }
        }
        return $field;
    }
Nirmal Ram
quelle
3
Mach das nicht. Ich kann sehen, dass mindestens zwei Dinge mit Ihrem Code falsch sind: Die Zuweisung zu $ ​​field funktioniert nicht (das $ fields-Array wird dabei nie geändert), und return $ field gibt das singuläre Feld zurück, nicht das Array.
Staplerfahrer