Se as estruturas de controle ensinam o programa a tomar decisões, as estruturas de repetição ensinam o programa a ter persistência. Repetir uma ação dez, cem ou um milhão de vezes sem escrever o código uma única vez extra — isso é o poder dos loops.
O PHP oferece quatro estruturas de repetição: for, foreach, while e do while. Cada uma tem um contexto onde brilha. Entender qual usar em cada situação é uma das marcas de um desenvolvedor experiente.
for
O for é ideal quando você sabe de antemão quantas vezes quer repetir algo. Sua estrutura tem três partes: inicialização, condição de continuação e incremento.
<?php
// Estrutura: for (inicialização; condição; incremento)
// 1. Inicialização: executada UMA vez, no início
// 2. Condição: verificada ANTES de cada iteração — se false, para
// 3. Incremento: executado APÓS cada iteração
for ($i = 0; $i < 5; $i++) {
echo "Iteração $i\n";
}
// Saída: Iteração 0, Iteração 1, Iteração 2, Iteração 3, Iteração 4
// Contando de trás para frente
for ($i = 5; $i > 0; $i--) {
echo "$i ";
}
// Saída: 5 4 3 2 1
// Incremento de dois em dois
for ($i = 0; $i <= 10; $i += 2) {
echo "$i "; // 0 2 4 6 8 10
}
// Iterando sobre um array com índice numérico
$frutas = ["maçã", "banana", "laranja", "uva"];
for ($i = 0; $i < count($frutas); $i++) {
// count() retorna o número de elementos do array
echo "$i: {$frutas[$i]}\n";
}
// 0: maçã
// 1: banana
// 2: laranja
// 3: uva
foreach
O foreach é a estrutura de repetição mais usada no PHP cotidiano. Ele foi feito especificamente para iterar sobre arrays e objetos, sem a necessidade de controlar um índice manualmente.
<?php
$frutas = ["maçã", "banana", "laranja", "uva"];
// Forma simples — acessa apenas o valor
foreach ($frutas as $fruta) {
echo $fruta . "\n";
}
// Forma com chave e valor — acessa índice e valor
foreach ($frutas as $indice => $fruta) {
echo "$indice: $fruta\n";
}
// 0: maçã
// 1: banana
// 2: laranja
// 3: uva
// foreach com array associativo (chave => valor)
$pessoa = [
"nome" => "Ana",
"idade" => 28,
"cidade" => "São Paulo",
];
foreach ($pessoa as $chave => $valor) {
echo "$chave: $valor\n";
}
// nome: Ana
// idade: 28
// cidade: São Paulo
// foreach com array de arrays — muito comum em dados de banco
$usuarios = [
["nome" => "Ana", "idade" => 28],
["nome" => "Carlos", "idade" => 35],
["nome" => "Beatriz","idade" => 22],
];
foreach ($usuarios as $usuario) {
// Cada $usuario é um array associativo
echo "{$usuario['nome']} tem {$usuario['idade']} anos.\n";
}
Modificando valores com foreach por referência
Por padrão, o foreach trabalha com uma cópia do valor. Se você precisar modificar os elementos originais do array durante a iteração, use o operador & para passar por referência:
<?php
$precos = [10.0, 25.5, 8.0, 42.0];
// Sem referência — $preco é uma cópia, o array original não muda
foreach ($precos as $preco) {
$preco *= 1.1; // aplica 10% de aumento — mas não salva!
}
var_dump($precos[0]); // float(10) — não mudou
// Com referência (&) — modifica o array original
foreach ($precos as &$preco) {
$preco *= 1.1; // agora salva no array original
}
unset($preco); // IMPORTANTE: sempre destrua a referência após o loop
// Sem isso, a variável $preco ainda aponta para o último elemento
// e pode causar bugs sutis se o array for reutilizado
var_dump($precos[0]); // float(11) — mudou corretamente
O unset($preco) após o loop é uma das armadilhas mais clássicas do PHP. Nunca se esqueça dele ao usar referências em foreach.
while
O while repete enquanto uma condição for verdadeira. É ideal quando você não sabe de antemão quantas iterações serão necessárias — o loop termina quando a condição se torna falsa.
<?php
// Estrutura básica
$contador = 0;
while ($contador < 5) {
echo "Contador: $contador\n";
$contador++; // sem isso, loop infinito!
}
// Exemplo prático: lendo um arquivo linha por linha
// fgets() retorna false quando chega ao fim do arquivo
$arquivo = fopen("dados.txt", "r");
if ($arquivo) {
while (($linha = fgets($arquivo)) !== false) {
// processa cada linha
echo trim($linha) . "\n";
}
fclose($arquivo);
}
// Simulando paginação — avança páginas enquanto houver resultados
$pagina = 1;
$porPagina = 10;
$totalRegistros = 47;
while (($pagina - 1) * $porPagina < $totalRegistros) {
$inicio = ($pagina - 1) * $porPagina + 1;
$fim = min($pagina * $porPagina, $totalRegistros);
echo "Processando registros $inicio a $fim\n";
$pagina++;
}
// Processando registros 1 a 10
// Processando registros 11 a 20
// Processando registros 21 a 30
// Processando registros 31 a 40
// Processando registros 41 a 47
do while
O do while é semelhante ao while, mas com uma diferença fundamental: o bloco de código é executado pelo menos uma vez antes de verificar a condição. Isso é útil quando você precisa que o código rode ao menos uma iteração independentemente da condição.
<?php
// do while garante ao menos uma execução
$tentativas = 0;
do {
echo "Tentativa $tentativas\n";
$tentativas++;
} while ($tentativas < 3);
// Tentativa 0
// Tentativa 1
// Tentativa 2
// Caso clássico: validação de entrada do usuário
// (em ambiente CLI — linha de comando)
do {
$entrada = readline("Digite um número entre 1 e 10: ");
$numero = (int) $entrada;
} while ($numero < 1 || $numero > 10);
echo "Você digitou: $numero";
// Processamento com retry — tenta operação até ter sucesso ou esgotar tentativas
$maxTentativas = 3;
$tentativa = 0;
$sucesso = false;
do {
$tentativa++;
// simula uma operação que pode falhar
$sucesso = rand(0, 1) === 1;
echo "Tentativa $tentativa: " . ($sucesso ? "sucesso" : "falhou") . "\n";
} while (!$sucesso && $tentativa < $maxTentativas);
break e continue
Dois comandos que controlam o fluxo dentro de loops:
break— interrompe o loop completamentecontinue— pula para a próxima iteração, ignorando o restante do bloco atual
<?php
$numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// break — para o loop quando encontra o primeiro número maior que 5
foreach ($numeros as $n) {
if ($n > 5) {
break; // sai do foreach completamente
}
echo "$n "; // 1 2 3 4 5
}
// continue — pula os números pares
foreach ($numeros as $n) {
if ($n % 2 === 0) {
continue; // vai para a próxima iteração
}
echo "$n "; // 1 3 5 7 9
}
// break com nível numérico — quebra loops aninhados
// break 2 sai de dois níveis de loop de uma vez
for ($i = 0; $i < 3; $i++) {
for ($j = 0; $j < 3; $j++) {
if ($i === 1 && $j === 1) {
break 2; // sai dos dois loops
}
echo "($i,$j) ";
}
}
// (0,0) (0,1) (0,2) (1,0)
Evitando loops infinitos
Um loop infinito trava o processo PHP e pode derrubar o servidor. As causas mais comuns são:
<?php
// ✗ LOOP INFINITO — condição nunca se torna false
$i = 0;
while ($i < 10) {
echo $i;
// esquecemos de incrementar $i!
}
// ✗ LOOP INFINITO — incremento errado
for ($i = 10; $i > 0; $i++) { // $i começa em 10 e só aumenta
echo $i;
}
// ✓ Sempre verifique:
// 1. A variável de controle está sendo modificada dentro do loop?
// 2. A condição de parada é realmente atingível?
// 3. Há algum caso extremo (array vazio, valor zero) que precisa ser tratado?
// Proteção com contador de segurança — útil em loops complexos
$maxIteracoes = 1000;
$iteracao = 0;
while (condicaoComplexaDificilDeVerificar()) {
if ($iteracao++ > $maxIteracoes) {
throw new RuntimeException("Loop excedeu o limite de segurança.");
}
// processamento...
}
Qual loop usar em cada situação
<?php
$nomes = ["Ana", "Bruno", "Carla"];
// foreach — iterando arrays ou coleções (uso mais comum)
foreach ($nomes as $nome) {
echo $nome . "\n";
}
// for — quando o índice numérico importa ou você sabe o número de iterações
for ($i = 0; $i < count($nomes); $i++) {
echo "$i: {$nomes[$i]}\n";
}
// while — condição desconhecida, leitura de streams, retries
$posicao = 0;
while ($posicao < count($nomes)) {
echo $nomes[$posicao] . "\n";
$posicao++;
}
// do while — quando precisa de ao menos uma execução garantida
$tentativa = 0;
do {
echo "Tentativa $tentativa\n";
$tentativa++;
} while ($tentativa < 3);
Boas práticas em loops
Prefira foreach para arrays. É mais legível, menos propenso a erros de índice e expressa melhor a intenção de "percorrer cada item".
Evite modificar o array que está sendo iterado. Se precisar filtrar ou transformar, prefira funções como array_filter() e array_map() — veremos no próximo módulo.
Não chame funções pesadas na condição do for. O código a seguir chama count() a cada iteração:
<?php
// ✗ count() é chamado em cada iteração
for ($i = 0; $i < count($array); $i++) { ... }
// ✓ Calcule uma vez só, antes do loop
$total = count($array);
for ($i = 0; $i < $total; $i++) { ... }
Sempre destrua referências após foreach com &. Como vimos, unset($variavel) após o loop é obrigatório.
Nomeie a variável de iteração com clareza. $usuario é melhor que $u. $produto é melhor que $p. $i é aceitável apenas para contadores numéricos simples.
Resumo
| Estrutura | Quando usar |
|---|---|
for |
Número de iterações conhecido, índice numérico importa |
foreach |
Iterar arrays e objetos — uso mais comum no PHP |
while |
Condição desconhecida, streams, operações com retry |
do while |
Ao menos uma execução é garantida antes de verificar |
break |
Interromper o loop completamente |
continue |
Pular para a próxima iteração |
break N |
Sair de N níveis de loops aninhados |
Referências e leituras para aprofundar
-
Estruturas de repetição — Manual oficial do PHP https://www.php.net/manual/pt_BR/language.control-structures.php Documentação completa de
for,foreach,whileedo whilecom todos os detalhes de comportamento. -
foreach — Manual oficial do PHP https://www.php.net/manual/pt_BR/control-structures.foreach.php Documentação específica do
foreach, incluindo o comportamento de referências com&e as notas de compatibilidade. -
array_map, array_filter, array_walk — php.net https://www.php.net/manual/pt_BR/ref.array.php Funções funcionais que substituem loops em muitos casos. Veremos em detalhes no Módulo 2, mas vale uma espiada agora.
-
PHP: The Right Way — Arrays https://phptherightway.com/#arrays Seção sobre arrays e boas práticas de iteração, complementando o conteúdo deste artigo.
-
HUNT, Andrew; THOMAS, David. The Pragmatic Programmer. 20th Anniversary Edition. Addison-Wesley, 2019. https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/ Capítulo sobre loops e estruturas de dados — leitura que transcende qualquer linguagem específica.
-
Generators — Manual oficial do PHP https://www.php.net/manual/pt_BR/language.generators.php Tema avançado para explorar depois: generators permitem iterar sobre grandes conjuntos de dados sem carregá-los todos na memória. Uma evolução natural dos loops.