ti-enxame.com

PHP foreach alterar valores de matriz originais

Eu sou muito novo em arrays multidimensionais, e isso está me incomodando muito.

Minha matriz é a seguinte:

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

Então eu tenho uma função verificando se essas entradas estão preenchidas, se forem necessárias.

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

Agora meu problema é essa linha

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

Eu quero mudar o conteúdo da matriz original, desde que eu estou retornando isso, mas como faço para obter o nome da matriz atual (nomes neste exemplo) no meu loop foreach?

118
Jeppe

Em PHP, passar por referência (&) é ... controverso. Eu recomendo não usar a menos que você saiba por que você precisa e teste os resultados.

Eu recomendaria fazer o seguinte:

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

Basicamente, use $field quando precisar dos valores e $fields[$key] quando precisar alterar os dados.

218
Vlad Preda

Use &:

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

& passa um valor da matriz como referência e não cria uma nova instância da variável. Assim, se você alterar a referência, o valor original será alterado.

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

Editar 2018
Essa resposta parece ser favorecida por muitas pessoas na internet, e é por isso que decidi adicionar mais informações e palavras de cautela.
Embora passar por referência em foreach (ou funções) seja uma solução limpa e curta, para muitos iniciantes isso pode ser uma armadilha perigosa.

  1. Loops em PHP não têm seu próprio escopo. - @Mark Amery

    Isso pode ser um problema sério quando as variáveis ​​estão sendo reutilizadas no mesmo escopo. Outra pergunta SO ilustra bem porque isso pode ser um problema.

  2. Como foreach depende do ponteiro interno da matriz em PHP 5, alterá-lo dentro do loop pode levar a um comportamento inesperado. - PHP docs para foreach

    Desativar um registro ou alterar o valor de hash (a chave) durante a iteração no mesmo loop pode levar a comportamentos potencialmente inesperados em PHP <7. O problema fica ainda mais complicado quando o próprio array é uma referência.

  3. Foreach desempenho.
    Em geral, PHP prefere passar por valor devido ao recurso copy-on-write. Isso significa que internamente PHP não criará dados duplicados, a menos que a cópia precise ser alterada. É discutível se passar por referência em foreach ofereceria uma melhoria de desempenho. Como é sempre o caso, você precisa testar seu cenário específico e determinar qual opção usa menos memória e tempo de CPU. Para mais informações, veja a postagem SO vinculada abaixo por NikiC.

  4. Legibilidade do código.
    Criar referências em PHP é algo que rapidamente sai do controle. Se você é um novato e não tem controle total sobre o que está fazendo, é melhor ficar longe das referências. Para mais informações sobre o operador &, dê uma olhada neste guia: Referência - O que este símbolo significa em PHP?
    Para aqueles que querem aprender mais sobre esta parte da linguagem PHP: PHP References Explained

Uma explicação técnica muito boa feita pelo @NikiC da lógica interna de PHP foreach loops:
Como PHP 'foreach' realmente funciona?

127
Dharman

Use foreach($fields as &$field){ - então você trabalhará com o array original.

aqui é mais sobre passar por referência.

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

Isto é o que eu sugiro passar por referência

0
Sagar Kadam