Todo o programador WordPress sabe como executar um loop simples. Mas o que acontece quando o cliente pergunta: “Mostre-me todos os Produtos, que estão na Coleção de Verão (Categoria) E Vermelho (Tag), MAS exclua os itens Esgotados?”
De repente, query_posts (Deus me livre) ou um simples cat=5 não será suficiente.
Precisa de WP_Query Avançado.
Neste guia, vamos dominar tax_query, meta_query e as otimizações de performance que separam os juniores dos seniores.
1. A anatomia da tax_query (consultas de taxonomia)
Esqueça cat ou tag_id. São propriedades legadas.
tax_query é padrão, poderoso e permite lógica complexa.
Cenário: Múltiplas taxonomias (relação and)
Quer filmes que sejam “Ação” (Género) E de “2026” (Ano).
$args = [
'post_type' => 'movie',
'tax_query' => [
'relation' => 'AND', // Ambas as condições devem ser verdadeiras
[
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => 'action',
],
[
'taxonomy' => 'year',
'field' => 'slug',
'terms' => '2026',
],
],
];
$query = new WP_Query( $args );
Cenário: Lógica “or” complexa
Quer produtos que estejam OU “Em Promoção” OU “Liquidação”.
$args = [
'post_type' => 'product',
'tax_query' => [
'relation' => 'OR',
[
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'on-sale',
],
[
'taxonomy' => 'product_label',
'field' => 'slug',
'terms' => 'clearance',
],
],
];
2. “Posts relacionados” dinâmicos por taxonomia
Um dos requisitos mais comuns são “Posts Relacionados”. Não use um plugin. São 10 linhas de código.
function wppoland_get_related_posts() {
$current_id = get_the_ID();
$terms = get_the_terms( $current_id, 'category' );
if ( empty( $terms ) ) return [];
// Obter IDs de todos os termos anexados ao post atual
$term_ids = wp_list_pluck( $terms, 'term_id' );
$args = [
'category__in' => $term_ids,
'post__not_in' => [ $current_id ], // Excluir o próprio
'posts_per_page' => 3,
'orderby' => 'rand', // Aleatório
'no_found_rows' => true, // BOOST DE PERFORMANCE
];
return new WP_Query( $args );
}
3. Otimização de performance (a parte senior)
O WP_Query padrão é pesado. Conta todas as linhas (para paginação) e faz cache de tudo.
Se estiver a executar um loop num widget ou sidebar, não precisa de paginação.
Otimize os seus argumentos de consulta:
$args = [
'posts_per_page' => 5,
// 1. Não contar linhas totais (Poupa um SQL CALC_FOUND_ROWS)
'no_found_rows' => true,
// 2. Não atualizar cache de meta (Se não exibir campos personalizados)
'update_post_meta_cache' => false,
// 3. Não atualizar cache de termos (Se não exibir tags/categorias)
'update_post_term_cache' => false,
// 4. Retornar apenas IDs (Se apenas verificar a existência)
// 'fields' => 'ids',
];
4. Misturar meta_query e tax_query
E-commerce no mundo real precisa frequentemente de ambos. “Mostre T-Shirts (Taxonomia) que custam menos de 20€ (Meta).”
$args = [
'post_type' => 'product',
'tax_query' => [
[
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 't-shirts',
]
],
'meta_query' => [
[
'key' => '_price',
'value' => 20,
'compare' => '<=',
'type' => 'NUMERIC' // Crítico para comparação numérica!
]
]
];
Resumo
- Use sempre a sintaxe de array
tax_queryem vez de argumentos de string legados. - Use
'no_found_rows' => truesempre que a paginação não for necessária. - Entenda os filtros (
relationAND/OR) para construir consultas lógicas complexas.
A sua base de dados (e os seus utilizadores) vão agradecer-lhe.


