PHP foreach change les valeurs d'origine du tableau

143

Je suis très nouveau dans les tableaux multidimensionnels, et cela me dérange beaucoup.

Mon tableau est le suivant:

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

Ensuite, j'ai une fonction vérifiant si ces entrées sont remplies, si elles sont nécessaires.

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

Maintenant mon problème est cette ligne

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

Je souhaite modifier le contenu du tableau d'origine, car je le renvoie, mais comment obtenir le nom du tableau actuel (noms dans cet exemple) dans ma boucle foreach?

Jeppe
la source
1
duplication possible de PHP - Modifier l'objet courant dans la boucle foreach
PhoneixS
1
Peu importe à quel point vous êtes nouveau (ou avez été) - c'est quelque chose que vous pouvez lire dans la documentation PHP: php.net/manual/en/control-structures.foreach.php
Nikolay Ivanov

Réponses:

261

En PHP, passer par reference ( &) est ... controversé. Je recommande de ne pas l'utiliser sauf si vous savez pourquoi vous en avez besoin et de tester les résultats.

Je recommanderais de faire ce qui suit:

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

Donc, utilisez essentiellement $fieldlorsque vous avez besoin des valeurs et $fields[$key]lorsque vous devez modifier les données.

Vlad Preda
la source
Bien, cela fonctionne! J'ai essayé quelque chose comme ça en premier, mais je suppose que j'ai foiré un endroit :) Maintenant, je vais utiliser votre exemple mille fois et ne jamais oublier! :)
Jeppe
Heureux que cela ait aidé. Aussi, je recommande de lire l'article que j'ai lié, ainsi que la documentation officielle de foreach ( php.net/manual/ro/control-structures.foreach.php )
Vlad Preda
4
En bout de ligne: si vous allez changer le tableau / la variable, vous devez utiliser une référence. C'est plus rapide, plus propre et plus lisible.
Lulu
2
Je suis curieux de savoir pourquoi le passage par référence dans un foreachdevrait être controversé? Ce n'est pas comme si c'était un appel de fonction avec des effets secondaires cachés ou quoi que ce soit.
UncaAlby
1
Merci de dire que "passer par référence (&) est ... controversé", plutôt que "ne pas passer par référence" ou "passer par référence est mauvais". Moins susceptible de déclencher une guerre des flammes. :)
Sean the Bean
163

Utilisez &:

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

&transmet une valeur du tableau comme référence et ne crée pas de nouvelle instance de la variable. Ainsi, si vous modifiez la référence, la valeur d'origine changera.

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

Edit 2018
Cette réponse semble être favorisée par beaucoup de gens sur Internet, c'est pourquoi j'ai décidé d'ajouter plus d'informations et de mises en garde.
Bien que le passage par référence dans foreach(ou fonctions) soit une solution claire et courte, pour de nombreux débutants, cela peut être un écueil dangereux.

  1. Les boucles en PHP n'ont pas leur propre portée. - @Mark Amery

    Cela peut être un problème sérieux lorsque les variables sont réutilisées dans la même portée. Une autre question SO illustre bien pourquoi cela pourrait être un problème.

  2. Comme foreach repose sur le pointeur de tableau interne de PHP 5, le modifier dans la boucle peut entraîner un comportement inattendu. - Documentation PHP pour foreach

    La suppression d'un enregistrement ou la modification de la valeur de hachage (la clé) lors de l'itération sur la même boucle pourrait conduire à des comportements potentiellement inattendus dans PHP <7. Le problème se complique encore lorsque le tableau lui-même est une référence.

  3. Performance Foreach.
    En général, PHP préfère le passage par valeur en raison de la fonctionnalité de copie sur écriture. Cela signifie qu'en interne PHP ne créera pas de données dupliquées à moins que la copie de celles-ci ne doive être modifiée. On peut se demander si le passage par référence foreachoffrirait une amélioration des performances. Comme c'est toujours le cas, vous devez tester votre scénario spécifique et déterminer quelle option utilise moins de mémoire et de temps cpu. Pour plus d'informations, voir l'article SO lié ci-dessous par NikiC.

  4. Lisibilité du code.
    Créer des références en PHP est quelque chose qui devient rapidement incontrôlable. Si vous êtes novice et que vous n'avez pas le contrôle total de ce que vous faites, il est préférable de rester à l'écart des références. Pour plus d'informations sur l' &opérateur, consultez ce guide: Référence - Que signifie ce symbole en PHP?
    Pour ceux qui veulent en savoir plus sur cette partie du langage PHP : Références PHP expliquées

Une très belle explication technique de @NikiC sur la logique interne des boucles PHP foreach:
Comment fonctionne PHP «foreach»?

Dharman
la source
Mis à part les problèmes répertoriés, je recommande d'ajouter unset($value);après le foreachcrochet fermant, pour garantir que la variable par référence n'est plus disponible après l'itération. 3v4l.org/2V2AQ
fyrye
15

Utilisez foreach($fields as &$field){- vous travaillerez donc avec le tableau d'origine.

En savoir plus sur le passage par référence.

k102
la source
@RBA pls se réfèrent aux réponses ci-dessus - ils ont beaucoup plus de détails et de mises à jour - Je n'utilise pas php depuis un moment maintenant, donc je ne suis pas au courant de mises à jour à ce sujet
k102
1
function checkForm(& $fields){
    foreach($fields as $field){
        if($field['required'] && strlen($_POST[$field['name']]) <= 0){
            $fields[$field]['value'] = "Some error";
        }
    }
    return $fields;
}

C'est ce que je suggérerais de passer par référence

Sagar Kadam
la source
Cette technique est utilisée pour changer la valeur de la variable d'origine. puisque PHP prend en charge la technique Pass by Value. Nous devons ajouter le caractère '&' devant la variable pour indiquer cette valeur à passer par référence
Sagar Kadam
1
Alors pourquoi revenir encore $fields?
MAZux
C'est la pire réponse des 3 suggérées. Pour quiconque tombe sur cette réponse, veuillez ne pas concevoir vos fonctions pour modifier les données en place et les renvoyer. Pour l'auteur original: Vous n'avez fourni aucune explication sur les raisons pour lesquelles cette solution serait meilleure que les autres, ni sur son fonctionnement.
Dharman
-6

Essaye ça

function checkForm($fields){
        foreach($fields as $field){
            if($field['required'] && strlen($_POST[$field['name']]) <= 0){
                $field['value'] = "Some error";
            }
        }
        return $field;
    }
Nirmal Ram
la source
3
Ne faites pas cela. Je peux voir au moins deux choses qui ne vont pas avec votre code: l'assignation à $ field ne fonctionne pas (le tableau $ fields n'est jamais modifié lorsque vous faites cela), et return $ field renvoie le champ singulier, pas le tableau.
Staplerfahrer