Menu

foreach no PHP: chave e valor, índice e referência

foreach ($array as $value) visita cada elemento de um array, e foreach ($array as $key => $value) também dá a chave. Veja como obter o índice, alterar valores por referência e a pegadinha do unset(), break e continue, arrays aninhados, list() no foreach e como montar HTML.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

foreach ($array as $value) executa o bloco uma vez para cada elemento, com $value valendo o elemento atual. Para obter a chave também, escreva foreach ($array as $key => $value).

O foreach funciona com qualquer array, sejam quais forem as chaves, e você nunca precisa controlar um contador ou verificar um tamanho. É o loop que você mais vai escrever em PHP.

Percorrer chaves e valores

Em $key => $value, os nomes são você quem escolhe: $name => $age, $id => $user, $k => $v. Numa lista, as chaves são as posições 0, 1, 2. Num array associativo, são as chaves string que você definiu.

O último loop mostra um detalhe que surpreende: uma chave string que parece um número inteiro, como "1", é guardada como o inteiro 1. "01" não é um inteiro canônico, então continua string.

Obter o índice no foreach

Numa lista, a chave é o índice, então foreach ($items as $i => $item) é tudo de que você precisa. Num array associativo não há posição numérica, então mantenha um contador. Para tratar o primeiro ou o último elemento de outro jeito, compare a chave com array_key_first() ou array_key_last().

O último loop imprime uma vírgula entre os nomes, mas não depois do último. Para essa tarefa exata, implode(', ', array_keys($scores)) é mais curto; a verificação com array_key_last() serve para quando a última volta precisa de uma lógica diferente, não só de outro separador.

Alterar valores do array no foreach (por referência)

$value é uma cópia. Atribuir a ele não muda nada no array. Para mudar o array, percorra por referência com &$value ou escreva de volta pela chave.

Os dois funcionam. A versão com a chave não deixa estado escondido depois do loop, e é por isso que muitas equipes a preferem. Para montar um novo array em vez de alterar um, o array_map() é outra opção.

Uma pergunta relacionada: o que acontece se você adicionar elementos durante o loop? Um foreach simples percorre o array como ele estava quando o loop começou, então $prices[] = ... dentro dele não cria voltas extras. Um loop por referência percorre o array vivo e visita os novos elementos.

A pegadinha do unset() com foreach por referência

Depois de foreach ($arr as &$v), a variável $v continua sendo uma referência ao último elemento do array. Se você reutilizar o nome $v depois num loop normal, cada volta escreve nesse último elemento. Rode e olhe o último item:

O segundo loop atribui A, depois B, depois o próprio valor do último elemento a $letters[2], e na última volta essa posição já guarda B. A correção é uma linha: coloque unset($v); logo depois de cada foreach por referência.

break e continue no foreach

break sai do loop, continue pula para o próximo elemento. Um padrão comum é a busca: percorra até encontrar o que precisa e dê break, para que o resto do array não seja verificado.

Em loops aninhados, break 2 sai do loop interno e do que está em volta dele, e continue 2 pula para a próxima volta do loop externo.

Arrays aninhados e foreach com list()

Linhas de dados são arrays dentro de um array. Percorra as linhas e depois cada linha, ou extraia os campos direto na linha do foreach com desestruturação de array: [$a, $b] para listas, ['key' => $var] para linhas associativas. list($a, $b) é a grafia antiga de [$a, $b].

A página sobre desestruturação tem mais sobre a sintaxe [...] =, incluindo elementos pulados e padrões aninhados.

Montar uma lista ou tabela HTML com foreach

Num template, a forma com dois pontos foreach (...): com endforeach; mantém o loop legível entre as tags. Este bloco monta uma tabela, e os cabeçalhos das colunas são links: clique num deles na aba Page e o mesmo script roda de novo com $_GET['sort'] definido, então as linhas voltam numa nova ordem.

Dois hábitos que valem copiar desse bloco: o valor sort da URL é comparado com uma lista de colunas permitidas antes de ser usado, e todo valor impresso no HTML que pode conter texto do usuário passa por htmlspecialchars().

foreach em null, num array vazio ou num objeto

Um array vazio não tem problema: o corpo nunca roda. null, uma string ou um número têm: o PHP imprime um aviso e pula o loop. Para $tags = null; foreach ($tags as $tag) ele imprime:

Warning: foreach() argument must be of type array|object, null given in /var/www/html/index.php on line 4

Isso acontece mais com dados que às vezes faltam, como um campo opcional num JSON decodificado. Use um array vazio como padrão com ??:

foreach ($data['tags'] ?? [] as $tag) {
    echo $tag;
}

O object nessa mensagem é real: um foreach sobre um objeto visita as propriedades visíveis de onde o loop roda (fora da classe, as públicas), com o nome da propriedade como chave. Classes que implementam Iterator ou IteratorAggregate, e generators, decidem por conta própria o que um foreach enxerga.

foreach, for ou array_map

UseQuando
foreachVocê quer cada elemento, com ou sem a chave. Funciona em qualquer array, lista ou associativo.
forVocê conta (1 a 100, um elemento sim e outro não) ou precisa dos vizinhos pelo índice ($a[$i - 1]). Veja o laço for.
array_map()Você monta um novo array transformando cada elemento, muitas vezes numa linha com fn.
array_filter()Você mantém só os elementos que passam num teste.

Um jeito rápido de decidir: se o corpo do loop só calcula um novo valor por elemento, array_map(fn($x) => $x * 2, $a) diz isso numa linha. Se ele tem efeitos colaterais (imprimir, salvar, contar várias coisas ao mesmo tempo) ou precisa de break, escreva o foreach.

Perguntas frequentes

Como obtenho a chave e o valor num foreach do PHP?

Use a forma com =>: foreach ($array as $key => $value) { echo "$key: $value"; }. Numa lista simples, a chave é o índice (0, 1, 2); num array associativo, é a chave string, como 'name'.

Como obtenho o índice num foreach do PHP?

Numa lista, a chave já é o índice: foreach ($items as $i => $item). Num array associativo, mantenha seu próprio contador: defina $i = 0; antes do loop e $i++ no fim de cada volta. array_key_first() e array_key_last() dizem qual chave é a primeira ou a última.

Como altero valores de um array dentro do foreach no PHP?

Percorra por referência com &: foreach ($prices as &$price) { $price *= 2; } unset($price);. Ou escreva pela chave: foreach ($prices as $key => $price) { $prices[$key] = $price * 2; }. Um simples $price = ... só altera uma cópia.

Por que o foreach por referência duplica o último elemento?

Depois de foreach ($arr as &$v), $v continua sendo uma referência ao último elemento. Um segundo foreach ($arr as $v) escreve cada valor nessa última posição, que acaba repetindo o penúltimo valor. Chame unset($v); logo depois do loop por referência.

Como saio de um foreach no PHP?

break; encerra o loop na hora e continue; pula para o próximo elemento. Em loops aninhados, break 2; sai do loop interno e do externo.

Ilustração das linguagens de programação do Coddy

Aprenda a programar com o Coddy

COMEÇAR