Como corrigir o loop infinito no Repeater Field do ACF PRO
O que é o ACF Repeater loop infinito?
O loop infinito no Repeater Field do ACF PRO é quando um template percorre as linhas do campo Repeater com have_rows sem avançar o ponteiro interno de linha, e o laço nunca termina. A função have_rows apenas verifica se há linhas e devolve verdadeiro ou falso. Quem move o ponteiro para a próxima linha é a função the_row, chamada dentro do while. Sem the_row, a condição continua verdadeira para sempre e o PHP reexecuta a mesma linha até o servidor cortar a requisição por tempo de execução ou por memória.
Como identificar
- A página com o Repeater fica carregando e nunca termina, e depois cai com Maximum execution time of 30 seconds exceeded.
- O log de erros do PHP registra Allowed memory size of X bytes exhausted na linha do template que tem o while have_rows.
- O mesmo conteúdo de uma única linha do Repeater aparece repetido centenas de vezes antes de a página travar.
- Em Repeater aninhado, o laço interno reusa o nome do campo do laço externo e o segundo nível nunca avança.
Antes de começar: Faça backup do arquivo do tema ou do template antes de editar o laço, e teste a correção em ambiente de staging. Um while have_rows mal fechado em produção pode derrubar a página inteira e estourar os recursos do servidor.
Como prevenir
- Copie sempre o padrão have_rows, while, the_row, get_sub_field da documentação do ACF em vez de escrever o laço de memória.
- Em Repeater aninhado, nomeie os sub campos de forma distinta do campo pai para nunca confundir os ponteiros.
- Quando o Repeater roda em listagens, feche cada iteração com reset_rows e teste a página com muitos itens em staging antes de publicar.
Causa
- O while have_rows não chama the_row no corpo do laço, então o ponteiro interno de linha nunca avança e a condição fica sempre verdadeira.
- Em Repeater aninhado, o laço interno usa o mesmo nome de campo do laço externo em vez do nome do sub campo, e os dois ponteiros se misturam.
- O código avalia have_rows com um nome de campo que não existe no post atual, e um have_rows mal posicionado fora do escopo da linha mantém o laço aberto.
- Uma chamada a get_field do mesmo Repeater dentro do while reabre o array e reposiciona o estado do laço, impedindo o ponteiro de chegar ao fim.
- O Repeater roda em uma página de listagem em loop de posts sem reset_rows entre os posts, e o estado de linha de um post vaza para o seguinte.
Como resolver
- Confirme que the_row está dentro do while: abra o template e garanta que cada laço de Repeater chama a função que avança o ponteiro como primeira instrução dentro do while. É a ausência dela que cria o laço sem fim.
- Use o padrão canônico de loop do ACF: estruture o laço com a verificação, o while que avança a linha e a leitura do sub campo, exatamente como a documentação do ACF orienta.
if ( have_rows('itens') ) { while ( have_rows('itens') ) { the_row(); $título = get_sub_field('título'); } } - Separe os ponteiros no Repeater aninhado: no laço interno, percorra o sub campo Repeater pelo nome dele, nunca pelo nome do campo do laço externo. Cada have_rows mantém o próprio ponteiro quando o nome está correto.
while ( have_rows('itens') ) { the_row(); while ( have_rows('sub_itens') ) { the_row(); } } - Não reabra o campo dentro do laço: remova qualquer chamada a get_field do mesmo Repeater de dentro do while, porque ela reposiciona o estado do laço e impede o ponteiro de chegar ao fim. Leia os valores apenas com get_sub_field.
- Resete o estado entre posts: quando o Repeater roda dentro de um loop de posts, chame a função de reset do ACF ao fim de cada iteração para o estado de linha de um post não vazar para o próximo.
reset_rows(); - Ative o log e isole a linha: ligue o log de erros do PHP e abra o registro: a mensagem de tempo de execução ou de memória aponta a linha exata do while have_rows que ficou aberta, o que confirma a causa antes de publicar a correção.
define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true );
PHP
<?php
// Repeater com filho aninhado, ponteiros separados e reset por post.
if ( have_rows( 'itens' ) ) {
while ( have_rows( 'itens' ) ) {
the_row(); // avanca o ponteiro do laco externo
$titulo = get_sub_field( 'titulo' );
echo esc_html( $titulo );
if ( have_rows( 'sub_itens' ) ) {
while ( have_rows( 'sub_itens' ) ) {
the_row(); // ponteiro proprio do laco interno
echo esc_html( get_sub_field( 'rotulo' ) );
}
}
}
}
reset_rows(); // limpa o estado quando o Repeater roda dentro de um loop de posts
Perguntas frequentes
O que causa o loop infinito no Repeater do ACF PRO?
Na maioria dos casos é a falta da função the_row dentro do while have_rows. A documentação do ACF é clara: have_rows só verifica se há linhas, e quem avança o ponteiro para a próxima é the_row. Sem ela, a condição fica sempre verdadeira e o laço nunca termina.
Por que a página cai com Maximum execution time?
O laço sem fim reexecuta a mesma linha do Repeater indefinidamente e consome todo o tempo de processamento da requisição. O PHP corta o script ao atingir o limite de tempo de execução e registra Maximum execution time exceeded apontando a linha do while have_rows.
Como o Repeater aninhado gera o loop infinito?
Quando o laço interno chama have_rows com o nome do campo do laço externo em vez do nome do sub campo, os dois ponteiros se confundem e o nível interno nunca chega ao fim. Use o nome correto do sub campo no laço interno para que cada have_rows mantenha o próprio ponteiro.
Posso usar get_field em vez de have_rows no Repeater?
Pode, mas get_field devolve o array bruto sem gerenciar o ponteiro de linha, então você precisa percorrer com foreach e ler cada índice na mão. Para iterar com segurança, o padrão recomendado é have_rows com the_row e get_sub_field, que controla o estado do laço por você.
Para que serve a função reset_rows nesse erro?
Ela limpa o estado interno de linha do ACF. Quando o Repeater roda dentro de um loop de posts, o estado de um post pode vazar para o seguinte e manter um laço aberto. Chamar reset_rows ao fim de cada iteração evita esse vazamento entre posts.
Como confirmo qual linha está travando antes de corrigir?
Ative o log de erros do PHP com WP_DEBUG e WP_DEBUG_LOG e abra o arquivo de log. A mensagem de tempo de execução ou de memória aponta o arquivo e a linha exata do while have_rows que ficou aberta, confirmando a causa antes de você publicar a correção.
Por que não devo chamar get_field do Repeater dentro do while?
Reabrir o mesmo Repeater com get_field dentro do laço reposiciona o estado interno e impede o ponteiro de chegar ao fim, mantendo o laço aberto. Dentro do while, leia os valores apenas com get_sub_field, que opera na linha atual sem mexer no ponteiro.














