Primeira e última iteração no foreach: Armadilhas e soluções em PHP

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que a pergunta "primeira e última iteração foreach" explode no Stack Overflow?



Se você já escreveu em PHP e tentou adicionar uma classe CSS ao primeiro elemento de uma lista ou inserir um separador após cada elemento, exceto o último, então você já enfrentou esse problema. No Stack Overflow, esta pergunta acumulou mais de 150.000 visualizações e centenas de comentários. Por quê? Porque o foreach é um loop poderoso, mas "cego": ele não sabe em qual iteração está.



Neste artigo, vamos analisar 4 abordagens funcionais em PHP 8.x, desde a ingênua até a profissional. Você aprenderá como evitar "gambiarras" e escrever código que não seja vergonhoso de mostrar em uma revisão de código.





O problema: por que o foreach não sabe seu próprio número?



Ao contrário do for, onde você tem um contador $i, o foreach opera com o ponteiro interno do array. Ele é ideal para iterações simples, mas quando é necessário executar uma ação "apenas para o primeiro" ou "apenas para o último" elemento, começam as complicações.



Exemplo de uma tarefa típica:

// Exibir uma lista de produtos separados por vírgula, mas sem vírgula após o último$items = ['Leite', 'Pão', 'Ovos', 'Queijo'];

foreach ($items as $item) { echo $item . ', '; // Opa, a última vírgula é desnecessária!}


Saída: Leite, Pão, Ovos, Queijo, — isso não é bonito. Vamos corrigir.



Método 1: Contador + count() — o clássico do gênero



A maneira mais óbvia é criar uma variável contadora e compará-la com o número total de elementos.



$items = ['Leite', 'Pão', 'Ovos', 'Queijo'];$total = count($items);$i = 1;

foreach ($items as $item) { if ($i === 1) { echo "<strong>Primeiro: $item</strong><br>"; } elseif ($i === $total) { echo "<em>Último: $item</em><br>"; } else { echo "$item<br>"; } $i++;}


Vantagens:

  • Simplicidade e legibilidade.
  • Funciona com qualquer array, incluindo associativos.


Desvantagens:

  • É preciso lembrar de usar count() e inicializar o contador.
  • Se o array estiver vazio, $total = 0, e a primeira iteração nunca ocorrerá — é necessário verificar.
  • Não é adequado para objetos Iterator (por exemplo, geradores).


Método 2: Flags e reset() / end() — elegância sem contador



Você pode não contar as iterações, mas simplesmente armazenar o primeiro e o último elemento do array antes de iniciar o loop.



$items = ['Leite', 'Pão', 'Ovos', 'Queijo'];

$first = reset($items); // 'Leite'$last = end($items); // 'Queijo'reset($items); // Retorna o ponteiro para o início!

foreach ($items as $key => $item) { if ($item === $first) { echo "Primeiro: $item"; } elseif ($item === $last) { echo "Último: $item"; } else { echo "$item"; }}


Importante! As funções reset() e end() alteram o ponteiro interno do array. Após end(), é necessário chamar reset(), caso contrário, o foreach não começará do início.



Vantagens:

  • Não precisa de contador.
  • Funciona com arrays associativos.


Desvantagens:

  • Perigo: se o array tiver valores duplicados (por exemplo, dois "Queijos"), o último elemento será identificado incorretamente.
  • Não é adequado para objetos Iterator.
  • Requer o reset manual do ponteiro.


Método 3: array_keys() — para arrays associativos e objetos



Se você precisa trabalhar com chaves (e não apenas com valores) ou com objetos Iterator, pode obter uma lista de todas as chaves e verificar o índice.



$items = ['a' => 'Lei                

Blogs

Book Recommendations