Symfony UX 3.5 estreia paginação com cursor, lookahead e integração com Doctrine

O Symfony UX 3.5 chegou com quase 90 pull requests incorporados desde a versão 3.4. A novidade que mais chama atenção é o UX Pagination, um pacote oficial para paginar consultas do Doctrine, arrays e fontes de dados customizadas sem obrigar a aplicação a transformar uma lista comum em um componente cheio de JavaScript.

A release também mexe em Twig Components, Autocomplete, Dropzone, Icons e no UX Toolkit. É uma atualização grande para o projeto, mas a paginação merece ser entendida separadamente porque tenta reunir três estratégias que normalmente acabam espalhadas entre bibliotecas, código do repositório e helpers próprios.

O que o UX Pagination resolve

O pacote symfony/ux-pagination recebe uma fonte ainda não paginada, resolve os parâmetros da requisição, busca apenas o recorte necessário e devolve um resultado iterável para o controller e o Twig. A instalação é feita com Composer:

composer require symfony/ux-pagination

Ele funciona com queries do Doctrine ORM e DBAL, arrays, callbacks e adapters próprios. A navegação renderizada no servidor usa links reais, então uma paginação básica não depende de Stimulus, Turbo ou outro código no navegador. Existe integração opcional com LiveComponent para atualizar a lista sem recarregar a página, mas os URLs continuam navegáveis e compartilháveis.

Três estratégias para problemas diferentes

O ponto mais interessante da API é não fingir que toda paginação precisa oferecer a mesma promessa. O Symfony UX 3.5 separa três estratégias:

  • Páginas numeradas: calcula o total, mostra números e permite saltar diretamente para uma página. É a opção familiar, mas normalmente exige uma consulta de contagem.
  • Lookahead: busca um item a mais para descobrir se existe uma próxima página. Evita o COUNT, mas deixa de oferecer um total exato e o salto para qualquer página.
  • Cursor bidirecional: continua a partir de uma posição assinada. É mais adequado quando registros podem entrar ou mudar enquanto a pessoa navega pela lista.

Essa divisão ajuda a escolher pelo comportamento necessário. Uma tela administrativa que precisa exibir “página 5 de 27” ainda combina com paginação numerada. Um feed que só mostra “anterior” e “próxima” pode evitar uma contagem cara com lookahead. Já uma lista muito movimentada tende a se beneficiar do cursor para não deslocar resultados entre requisições.

Como fica no controller e no Twig

O fluxo básico injeta PaginatorInterface, entrega a query ao paginador e envia o resultado para a view. Um exemplo reduzido fica assim:

public function __invoke(
    ProductRepository $repository,
    PaginatorInterface $paginator,
): Response {
    $products = $paginator->paginate(
        $repository->createListQuery(),
    );

    return $this->render('product/index.html.twig', [
        'products' => $products,
    ]);
}

No Twig, o mesmo objeto alimenta a lista e os links de navegação:

{% for product in products %}
    <article>{{ product.name }}</article>
{% endfor %}

{{ ux_pagination(products) }}

O pacote inclui temas padrão, Bootstrap e Tailwind. Também permite substituir o template sem misturar a lógica de paginação com as classes do projeto. É uma escolha sensata: o backend cuida de limites, posição e URLs, enquanto o tema decide como os controles aparecem.

A release vai além da paginação

O Symfony UX 3.5 também passa a aceitar Twig 4 em vários pacotes, incluindo Autocomplete, Dropzone, Icons, LiveComponent, Map, Turbo e TwigComponent. O Autocomplete deixa de exigir Doctrine e pode buscar opções em APIs, mecanismos de busca ou listas em memória por meio de uma interface própria.

Dropzone ganhou suporte a múltiplos arquivos, o Toolkit recebeu vinte novas receitas inspiradas no Shadcn e a documentação de acessibilidade dessas receitas trouxe correções reais para diálogos e layouts da direita para a esquerda. Houve ainda uma rodada de otimizações em TwigComponent e LiveComponent para evitar trabalho repetido durante a renderização.

Vale atualizar agora?

Para quem já usa Symfony UX, a versão tem melhorias úteis mesmo sem adotar o novo paginador. Ainda assim, vale revisar snapshots e testes que comparam HTML literalmente: a renderização de atributos dos componentes passou a usar a implementação do próprio Twig, e o SVG produzido por UX Icons também pode mudar.

O UX Pagination continua marcado como experimental, portanto sua API pode mudar. Faz sentido testá-lo em uma tela isolada antes de substituir uma solução estável em toda a aplicação. Também é melhor instalar a versão mais recente da linha 3.5, já que a 3.5.1 saiu poucas horas depois para corrigir duas integrações com o AssetMapper do Symfony 8.2.

Fontes