Skip to content

Tudo para WordPress, desenvolvimento web — e não só

🔧 Como tornar um tema WordPress compatível com WooCommerce: um guia completo para programadores

🔧 Como tornar um tema WordPress compatível com WooCommerce: um guia completo para programadores

Construir o seu próprio tema e quer integrar uma loja? Tecnicamente, o WooCommerce funciona com qualquer tema, uma vez que é apenas um plugin. Mas «funcionar» não significa «ter bom aspeto»: a grelha de produtos parte-se, as barras laterais deslocam-se e os estilos padrão entram em conflito com os seus.

O problema é mais profundo do que algumas regras de CSS. A partir do WooCommerce 3.3, um tema sem suporte declarado obtém uma renderização simplificada através de shortcodes e um aviso no painel de administração. Perde o controlo total sobre o layout.

Abaixo encontram-se snippets prontos a usar que cobrem tudo, desde a declaração de suporte até um carrinho dinâmico no menu. Cada um foi testado na versão atual do WooCommerce e está organizado por secção, das bases aos ajustes finos.

💡 Visão geral rápida:

  • Primeiro, o tema deve declarar explicitamente o suporte ao WooCommerce; sem isso, as substituições de templates e algumas funcionalidades não serão ativadas
  • Coloque o código num ficheiro separado (por exemplo inc/woocommerce.php) que carrega apenas quando o plugin está ativo
  • Configurar a grelha da loja requer dois filtros: um altera as colunas, o outro adiciona uma classe ao body
  • A galeria de produtos, zoom, lightbox e slider são ativados através de chamadas separadas a add_theme_support
  • O carrinho no menu deve atualizar via AJAX; utilize o filtro add_to_cart_fragments

1. Fundação: declarar suporte e verificar se o plugin está ativo

Em primeiro lugar, o tema deve dizer explicitamente ao WooCommerce: «Eu suporto-te.» Sem isto, o plugin não ativa as substituições de templates e mostra um aviso no painel de administração. A partir do WooCommerce 3.3, um tema sem suporte declarado obtém uma renderização simplificada através de shortcodes. Isto funciona, mas limita o seu controlo sobre o layout.

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce' );
3} );

É importante usar o hook after_setup_theme em vez do init, conforme recomendado pela documentação do WooCommerce. Desde a versão 3.3+, pode passar as definições da grelha diretamente:

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce', array(
3 'thumbnail_image_width' => 150,
4 'single_image_width' => 300,
5 'product_grid' => array(
6 'default_rows' => 3,
7 'min_rows' => 2,
8 'max_rows' => 8,
9 'default_columns' => 4,
10 'min_columns' => 2,
11 'max_columns' => 5,
12 ),
13 ) );
14} );

Estes parâmetros definem os valores padrão para o personalizador (WooCommerce → Imagens de Produtos / Catálogo de Produtos) e evitam que os utilizadores tenham de configurar a grelha manualmente.

Verificar se o plugin está ativo

Quando distribui um tema, não pode simplesmente despejar snippets do WooCommerce no final do functions.php porque causarão um erro fatal se o plugin não estiver ativo. O código deve carregar apenas quando o WooCommerce está em execução:

1define( 'MYTHEME_WOOCOMMERCE_ACTIVE', class_exists( 'WooCommerce' ) );
2
3if ( MYTHEME_WOOCOMMERCE_ACTIVE ) {
4 require_once get_template_directory() . '/inc/woocommerce.php';
5}

A constante é avaliada uma vez e, depois, em qualquer parte do seu tema, pode envolver as chamadas em if ( MYTHEME_WOOCOMMERCE_ACTIVE ). Isto é mais limpo do que chamar class_exists ou is_plugin_active de cada vez.

2. Gerir os estilos do WooCommerce

O WooCommerce vem com três ficheiros CSS: woocommerce-general, woocommerce-layout e woocommerce-smallscreen. Idealmente, não os remove, mas substitui-os no seu tema. Dessa forma, as extensões de terceiros do WooCommerce que dependem destas classes não se partem. Mas se estiver a escrever tudo de raiz e quiser controlo total, veja como removê-los.

Remover todos os estilos de uma vez:

1add_filter( 'woocommerce_enqueue_styles', '__return_empty_array' );

Ou remover seletivamente:

1function mytheme_remove_woo_styles( $styles ) {
2 unset( $styles['woocommerce-general'] );
3 unset( $styles['woocommerce-layout'] );
4 unset( $styles['woocommerce-smallscreen'] );
5 return $styles;
6}
7add_filter( 'woocommerce_enqueue_styles', 'mytheme_remove_woo_styles' );

Na prática, a segunda opção é mais comum: remove o woocommerce-layout (a grelha baseada em percentagens), mas mantém o woocommerce-general (botões, avisos, formulários) e substitui-os seletivamente com o seu próprio CSS usando maior especificidade.

3. Configurar as páginas da loja

Quantos produtos mostrar

O filtro loop_shop_per_page controla o número de produtos na página da loja e nos arquivos (categorias, etiquetas):

1function mytheme_woo_posts_per_page( $cols ) {
2 return 12;
3}
4add_filter( 'loop_shop_per_page', 'mytheme_woo_posts_per_page' );

Número de colunas na grelha

São necessários dois filtros aqui. Usar apenas loop_shop_columns não chega: ao contrário dos shortcodes do WooCommerce (que têm um wrapper com a classe columns-N), as páginas de loja não têm essa classe. Por isso, adicionamo-la ao body:

1function mytheme_woo_shop_columns( $columns ) {
2 return 4;
3}
4add_filter( 'loop_shop_columns', 'mytheme_woo_shop_columns' );
5
6function mytheme_woo_shop_columns_body_class( $classes ) {
7 if ( is_shop() || is_product_category() || is_product_tag() ) {
8 $classes[] = 'columns-4';
9 }
10 return $classes;
11}
12add_filter( 'body_class', 'mytheme_woo_shop_columns_body_class' );

Agora, no CSS, pode escrever seletores como .columns-4 ul.products li.product, e eles aplicar-se-ão especificamente à grelha da loja.

Título da loja

Por predefinição, o WooCommerce mostra «Shop» como título na página de loja. Se o seu tema já trata dos títulos de arquivo, esta duplicação atrapalha:

1add_filter( 'woocommerce_show_page_title', '__return_false' );

Se usar the_archive_title(), pode substituir o título pelo nome da página de loja (definido no painel de administração):

1function mytheme_woo_archive_title( $title ) {
2 if ( is_shop() && $shop_id = wc_get_page_id( 'shop' ) ) {
3 $title = get_the_title( $shop_id );
4 }
5 return $title;
6}
7add_filter( 'get_the_archive_title', 'mytheme_woo_archive_title' );

4. Galeria de produto: zoom, lightbox e slider

A partir do WooCommerce 3.0, foi introduzida uma nova galeria de produto baseada no FlexSlider, PhotoSwipe e jQuery Zoom. Nas versões 3.0 a 3.2, está desativada por predefinição e requer ativação explícita. A partir da 3.3, a galeria fica ativada para temas não WooCommerce e desativada para temas que declarem suporte; ativa os componentes de que precisa:

1add_theme_support( 'wc-product-gallery-slider' );
2add_theme_support( 'wc-product-gallery-zoom' );
3add_theme_support( 'wc-product-gallery-lightbox' );

Pode ativar apenas algumas funcionalidades: por exemplo, slider e zoom sim, mas substituir a lightbox pela sua própria solução Fancybox. Cada diretiva carrega os seus próprios scripts, por isso não ative o que não precisa.

Número de colunas para as miniaturas da galeria (abaixo da imagem principal do produto):

1function mytheme_woo_product_thumbnails_columns() {
2 return 4;
3}
4add_action( 'woocommerce_product_thumbnails_columns', 'mytheme_woo_product_thumbnails_columns' );

5. Produtos relacionados e cross-sells/up-sells

Na página de produto, o WooCommerce mostra os blocos «Produtos relacionados» e «Também pode gostar» (up-sells). A quantidade e a grelha são configuradas separadamente.

Quantos produtos relacionados mostrar:

1function mytheme_woo_related_posts_per_page( $args ) {
2 $args['posts_per_page'] = 4;
3 return $args;
4}
5add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_posts_per_page' );

Colunas para os blocos de up-sells e relacionados (a mesma história da grelha da loja): alteramos tanto as colunas como a classe no body:

1function mytheme_woo_single_loops_columns( $columns ) {
2 return 4;
3}
4add_filter( 'woocommerce_up_sells_columns', 'mytheme_woo_single_loops_columns' );
5
6function mytheme_woo_related_columns( $args ) {
7 $args['columns'] = 4;
8 return $args;
9}
10add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_columns', 10 );
11
12function mytheme_woo_single_loops_columns_body_class( $classes ) {
13 if ( is_singular( 'product' ) ) {
14 $classes[] = 'columns-4';
15 }
16 return $classes;
17}
18add_filter( 'body_class', 'mytheme_woo_single_loops_columns_body_class' );

Note que woocommerce_output_related_products_args tem dois filtros com prioridades diferentes: mytheme_woo_related_posts_per_page (predefinição 10) altera posts_per_page, e mytheme_woo_related_columns (prioridade 10) altera columns. Não entram em conflito porque trabalham com chaves diferentes no mesmo array $args.

6. Paginação e selo de saldo

Pode substituir as setas da paginação pelos ícones do seu tema:

1function mytheme_woo_pagination_args( $args ) {
2 $args['prev_text'] = '<i class="fa fa-angle-left"></i>';
3 $args['next_text'] = '<i class="fa fa-angle-right"></i>';
4 return $args;
5}
6add_filter( 'woocommerce_pagination_args', 'mytheme_woo_pagination_args' );

Substitua as classes do Font Awesome pelas suas próprias classes de ícones ou SVGs diretos.

O texto no selo de promoção (Sale!) é fácil de alterar. Isto é útil para sites noutros idiomas ou simplesmente para remover o ponto de exclamação:

1function mytheme_woo_sale_flash() {
2 return '<span class="onsale">' . esc_html__( 'Sale', 'woocommerce' ) . '</span>';
3}
4add_filter( 'woocommerce_sale_flash', 'mytheme_woo_sale_flash' );

Para outros idiomas, substitua 'Sale' pela sua tradução. A tradução será aplicada automaticamente se tiver os ficheiros MO do WooCommerce para esse idioma.

7. Carrinho dinâmico no menu

Este é provavelmente o elemento mais solicitado em qualquer tema de loja: um ícone de carrinho na navegação com o total atual. A implementação consiste em três partes: adicionar o elemento ao menu, gerar o HTML do carrinho e a atualização via AJAX.

1// Adding the link to the menu
2function mytheme_add_menu_cart_item( $items, $args ) {
3 if ( $args->theme_location === 'primary' ) {
4 $css_class = 'menu-item menu-item-type-cart menu-item-type-woocommerce-cart';
5 if ( is_cart() ) {
6 $css_class .= ' current-menu-item';
7 }
8 $items .= '<li class="' . esc_attr( $css_class ) . '">';
9 $items .= mytheme_menu_cart_item();
10 $items .= '</li>';
11 }
12 return $items;
13}
14add_filter( 'wp_nav_menu_items', 'mytheme_add_menu_cart_item', 10, 2 );
15
16// Cart HTML
17function mytheme_menu_cart_item() {
18 $cart_count = WC()->cart->cart_contents_count;
19 $css_class = 'wpex-menu-cart-total wpex-cart-total-' . intval( $cart_count );
20 $url = $cart_count ? WC()->cart->get_cart_url() : wc_get_page_permalink( 'shop' );
21 $html = WC()->cart->get_cart_total();
22 $html = str_replace( 'amount', '', $html );
23
24 return '<a href="' . esc_url( $url ) . '" class="' . esc_attr( $css_class ) . '">'
25 . '<span class="cart-icon"></span>'
26 . wp_kses_post( $html )
27 . '</a>';
28}
29
30// AJAX fragment update
31function mytheme_menu_cart_link_fragments( $fragments ) {
32 $fragments['.wpex-menu-cart-total'] = mytheme_menu_cart_item();
33 return $fragments;
34}
35add_filter( 'add_to_cart_fragments', 'mytheme_menu_cart_link_fragments' );

Ponto crítico: **não envolva estas funções em **is_admin(). Os pedidos AJAX do carrinho passam pelo admin-ajax.php e, se a função não estiver disponível no contexto de administração, a atualização do preço no menu simplesmente não funcionará. Substitua theme_location pelo identificador do seu menu (primary no exemplo).

8. Abordagem alternativa: o template woocommerce.php

Os hooks descritos acima são o método mais flexível e seguro em termos de atualizações. Mas se precisar de reformular radicalmente todo o wrapper da loja e da página de produto, existe um caminho através de um template separado.

Crie um ficheiro woocommerce.php na raiz do seu tema (uma cópia do page.php) e substitua o loop principal por uma chamada a woocommerce_content():

1<?php
2get_header(); ?>
3
4<div id="primary" class="content-area">
5 <main id="main" class="site-main">
6 <?php woocommerce_content(); ?>
7 </main>
8</div>
9
10<?php get_footer();
11

Este método é mais simples, mas tem um custo: um único template para todas as páginas do WooCommerce (a loja, as categorias e o detalhe do produto). Os ajustes finos (grelhas diferentes, sidebars diferentes em páginas diferentes) tornam-se mais difíceis. Escolha esta abordagem apenas se o seu tema atual realmente não se der bem com o WooCommerce ao nível da marcação e se estiver preparado para aceitar as limitações.

⁉️🤔 Perguntas frequentes

É obrigatório remover os estilos padrão do WooCommerce?

Não é obrigatório. Uma abordagem mais segura é mantê-los e substituir os seletores no seu tema com maior especificidade. Isto preserva a compatibilidade com extensões que dependem das classes padrão do WooCommerce. A remoção completa (__return_empty_array) só se justifica se estiver a construir um tema de loja de raiz e tiver a certeza de que nenhum plugin de terceiros irá adicionar elementos estilizados para o WooCommerce. Na maioria dos casos, desativar seletivamente o woocommerce-layout (a grelha percentual entra em conflito com flexbox e grids nos temas modernos), mantendo o woocommerce-general e o woocommerce-smallscreen e substituindo-os cuidadosamente através da cascata de CSS, é suficiente. Isto dá-lhe uma grelha limpa sem perder compatibilidade.

Porque é que alterar as colunas na loja não funciona?

Porque o filtro loop_shop_columns por si só não é suficiente. O WooCommerce usa classes .columns-N no wrapper para fazer a grelha funcionar, e estas são adicionadas automaticamente apenas aos shortcodes ([products columns="4"]). Nas páginas de loja e arquivos, este wrapper não existe, pelo que precisa de adicionar a classe ao body através do body_class. Os dois filtros da secção 3 resolvem este problema por completo.

O filtro loop_shop_columns altera a variável PHP que o WooCommerce passa para o template, mas a grelha CSS depende da classe do wrapper. Sem a classe columns-4 no body, os seus estilos ul.products li.product não têm um seletor de contexto e ou não se aplicam ou atingem todas as listas de produtos do site.

Preciso de reconstruir o tema após uma atualização do WooCommerce?

Se estiver a usar hooks (todos os snippets deste artigo), não. Os hooks mudam muito raramente. Se estiver a substituir templates (ficheiros de woocommerce/templates/), sim, precisa de comparar as suas cópias com as versões atuais após cada atualização principal. É exatamente por isso que a documentação oficial recomenda os hooks como o método de personalização preferencial.

Os hooks são um contrato. O WooCommerce garante a sua estabilidade entre versões. Os templates são uma implementação que pode mudar a qualquer momento: novas ações são adicionadas, a marcação muda, as classes são renomeadas. Nos cinco anos em que estes hooks existem (loop_shop_columns e woocommerce_output_related_products_args), a sua assinatura nunca mudou, enquanto o ficheiro content-product.php foi atualizado dezenas de vezes durante o mesmo período.

Posso usar o is_admin() para proteger as funções do carrinho?

Não, e esta é uma armadilha comum. Os pedidos AJAX do WooCommerce (adicionar ao carrinho, atualizar quantidade) são processados através do admin-ajax.php; neste contexto, o is_admin() devolve true. Se envolver as funções do carrinho em if ( ! is_admin() ), as atualizações de fragmentos AJAX (add_to_cart_fragments) deixarão de funcionar e o total no ícone do carrinho não mudará sem recarregar a página.

O envolvimento em ! is_admin() só deve ser usado para coisas que não devem ser executadas no admin (saída HTML do front-end), mas as funções de manipulação AJAX devem estar sempre disponíveis. Para o código da secção 7, não use o is_admin() de todo. O próprio WooCommerce chama os callbacks necessários através do seu manipulador AJAX, e a restrição quebrará a lógica.

Como adiciono suporte WooCommerce a um tema de blocos (FSE)?

Para temas de blocos, a declaração de suporte não mudou: o mesmo add_theme_support('woocommerce'). Mas em vez de hooks e substituição de templates PHP, trabalha no Editor do Site: o WooCommerce fornece blocos (Produtos, Pesquisa de Produtos, Carrinho, Finalizar Compra) que insere nos templates através do Appearance → Editor. Os ajustes finos são feitos através do theme.json e das variáveis CSS.

Os temas de blocos mudam fundamentalmente a abordagem: não escreve hooks PHP para o layout, mas monta visualmente as páginas a partir de blocos WooCommerce prontos a usar. Mas a base (add_theme_support no functions.php) permanece a mesma. Para ajustes finos que não podem ser feitos com blocos (por exemplo, texto personalizado no botão «Adicionar ao Carrinho»), os velhos e bons filtros deste artigo também funcionam em temas FSE.

Que estratégia escolher para o seu projeto

Se está a melhorar um tema existente, comece com os passos 1 e 2: declare o suporte e configure a grelha. Na maioria dos casos, isto é suficiente para que a loja tenha um aspeto decente. Depois, adicione apenas as correções que resolvem problemas específicos: uma galeria partida, uma paginação feia, a falta do carrinho no menu.

Se está a escrever um tema de raiz para venda ou distribuição, percorra a lista completa. Cada item acrescenta algo que os utilizadores esperam de um tema de loja «pronto a usar»: uma grelha personalizável, zoom nos produtos, um ícone de carrinho ao vivo. Coloque o código em inc/woocommerce.php e carregue-o com base na constante. Desta forma, o tema funciona igualmente bem como blog e como loja.

O ponto de partida é sempre o mesmo:

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce' );
3} );

Oito linhas. Todo o resto são detalhes que distinguem um tema «compatível» de um tema «feito à medida».