🎉 USE O CUPOM DESCONTO.FULL | 20% OFF acima de R$ 50,00

Como corrigir o loop infinito no Repeater Field do ACF PRO

Time Full Services Time Full Services
Tipo Page Builders
Nome do erro Loop infinito no Repeater Field do ACF PRO EN: ACF PRO Repeater Field infinite loop
Severidade Grave
Descrição O ACF Repeater loop infinito acontece quando o while de have_rows roda sem chamar the_row dentro dele: o ponteiro interno de linha nunca avança, a condição fica sempre verdadeira e o PHP repete a mesma linha até estourar Maximum Execution Time ou a memória.

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

  1. 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.
  2. 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');
        }
    }
  3. 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();
        }
    }
  4. 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.
  5. 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();
  6. 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.

Seja PRO.

Tenha acesso a snippets de código premium — PHP, JavaScript, CSS e HTML prontos para usar em seus projetos.

Conhecer o plano Pro →

Uma nova era para o WordPress.

A FULL Services redefine o CMS com uma arquitetura modular que transforma o WordPress em um motor de crescimento digital. 

Painéis personalizados

Um novo nível de controle para o WordPress. Acompanhe métricas, automações e evolução do seu site em um único painel visual.

A força por trás de grandes marcas

Para agências, estúdios e profissionais independentes que desejam oferecer soluções de alto nível com sua própria marca.

Componentes

Hero Sections

30 componentes

Seções de CTA

14 componentes

Login

14 componentes

Blog

14 componentes

Cabeçalhos

24 componentes

Seções de FAQ

53 componentes

Cadastro

53 componentes

Blog individual

53 componentes

Rodapés

28 componentes

Seções de contato

27 componentes

Seções de preços

27 componentes

Faixas

27 componentes

Portfólio

16 componentes

Seções de equipe

12 componentes

Números

12 componentes

Logotipos

12 componentes