Consultas personalizadas do WordPress – Usando a classe WP_Query

Publicados: 2021-02-06

O WordPress oferece uma ampla gama de funções prontas para uso que, na maioria dos casos, podem recuperar as informações necessárias do banco de dados. Mas ao desenvolver um site WordPress existem inúmeros cenários em que um filtro ou ação não é suficiente para alcançar o resultado desejado. Nesses casos. O WordPress oferece uma solução alternativa na forma da classe WP_Query .

Vamos dar uma olhada em como a classe WP_Query pode ser usada!

Casos de consulta personalizados

NOTA: Este artigo pressupõe que você tenha algum conhecimento de PHP e MySQL/MariaDB, além de estar familiarizado com o WordPress.

Qualquer que seja a página que você visita, o WordPress executa o que é chamado de 'consulta principal' para exibir o conteúdo. Então, quando você visita uma página como uma visão de categoria, por exemplo, um objeto WP_Query é criado nos bastidores e recupera todos os dados necessários do banco de dados para exibir a página.

O que o WP_Query basicamente faz é oferecer a você a capacidade de recuperar conteúdo do banco de dados do seu site sem ter que usar consultas SQL.

Para isso, basta definir os argumentos correspondentes às nossas necessidades e um novo objeto WP_Query será criado e traduzido em uma consulta SQL.

Um exemplo usando WP_Query

Se quisermos exibir postagens de uma categoria específica, dentro de outro modelo de categoria, é necessário criar um novo objeto de consulta.

Para os propósitos deste exemplo, ativamos o tema Twenty Twenty e criamos 2 posts em uma categoria chamada 'Categoria 1' e 2 posts em uma categoria chamada 'Serviços'.

Além disso, criamos um modelo de visualização de categoria personalizado para as postagens da 'Categoria 1'. O slug desta categoria é 'category-1', portanto, o arquivo sob a pasta do tema deve ser category-CATEGORYSLUG.php que no nosso caso é category-category-1.php .

Por favor, cole o seguinte no arquivo category-category-1.php .

 <?php /*** Custom Category 1 Template */ get_header(); ?> <main role="main"> <section class="site-content"> <div role="main"> <?php if ( have_posts() ) : ?> <header class="archive-header"> <h3 class="archive-title">Category: <?php single_cat_title( '', true ); ?></h3> </header> <?php while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; endif; ?> </div> </section> </main> <?php get_sidebar(); ?> <?php get_footer(); ?>

Antes do loop, usamos o método have_posts para determinar se há mais posts disponíveis no loop.

O the_post() é necessário para que o loop itere os posts e diga ao WordPress para passar para o próximo post do array posts.

Neste ponto, nossa visão de frontend da categoria ( https://mycompanyname.com/category/category-1/ ) será algo assim:

Eu sei que usando este pedaço de código nós deixamos de incluir muitas informações de postagem, mas por causa deste exemplo, é melhor mantê-lo simples e exibir apenas os títulos das postagens.

Para ver as propriedades do objeto de consulta que o WordPress criou para esta visualização, podemos simplesmente adicionar esta linha em nosso código após o endif; declaração.

 var_dump ( $wp_query->query_vars );

Agora, se você atualizar sua página, verá essas informações na lista de postagens:

 array(63) { ["category_name"]=> string(10) "category-1" ["error"]=> string(0) "" ["m"]=> string(0) "" ["p"]=> int(0) ["post_parent"]=> string(0) "" ["subpost"]=> string(0) "" ["subpost_id"]=> string(0) "" ["attachment"]=> string(0) "" ["attachment_id"]=> int(0) ["name"]=> string(0) "" ["pagename"]=> string(0) "" ["page_id"]=> int(0) ["second"]=> string(0) "" ["minute"]=> string(0) "" ["hour"]=> string(0) "" ["day"]=> int(0) ["monthnum"]=> int(0) ["year"]=> int(0) ["w"]=> int(0) ["tag"]=> string(0) "" ["cat"]=> int(16) ["tag_id"]=> string(0) "" ["author"]=> string(0) "" ["author_name"]=> string(0) "" ["feed"]=> string(0) "" ["tb"]=> string(0) "" ["paged"]=> int(0) ["meta_key"]=> string(0) "" ["meta_value"]=> string(0) "" ["preview"]=> string(0) "" ["s"]=> string(0) "" ["sentence"]=> string(0) "" ["title"]=> string(0) "" ["fields"]=> string(0) "" ["menu_order"]=> string(0) "" ["embed"]=> string(0) "" ["category__in"]=> array(0) { } ["category__not_in"]=> array(0) { } ["category__and"]=> array(0) { } ["post__in"]=> array(0) { } ["post__not_in"]=> array(0) { } ["post_name__in"]=> array(0) { } ["tag__in"]=> array(0) { } ["tag__not_in"]=> array(0) { } ["tag__and"]=> array(0) { } ["tag_slug__in"]=> array(0) { } ["tag_slug__and"]=> array(0) { } ["post_parent__in"]=> array(0) { } ["post_parent__not_in"]=> array(0) { } ["author__in"]=> array(0) { } ["author__not_in"]=> array(0) { } ["ignore_sticky_posts"]=> bool(false) ["suppress_filters"]=> bool(false) ["cache_results"]=> bool(true) ["update_post_term_cache"]=> bool(true) ["lazy_load_term_meta"]=> bool(true) ["update_post_meta_cache"]=> bool(true) ["post_type"]=> string(0) "" ["posts_per_page"]=> int(10) ["nopaging"]=> bool(false) ["comments_per_page"]=> string(2) "50" ["no_found_rows"]=> bool(false) ["order"]=> string(4) "DESC" }

Digamos que queremos exibir a lista de postagens que pertencem à categoria 'Serviços' nas postagens descritas acima. Como a página já criou um objeto de consulta para a categoria atual, teremos que contornar isso manipulando os argumentos de consulta principais existentes.

Vamos dar uma olhada nas maneiras como o WordPress nos permite conseguir isso.

A função query_posts

A função query_posts() é uma forma de alterar a consulta principal que o WordPress usa para exibir os posts. Ele faz isso colocando a consulta principal de lado e substituindo-a por uma nova consulta. Você pode ver isso por si mesmo no arquivo wp-includes/query.php onde é apresentado.

 function &query_posts($query) { unset($GLOBALS['wp_query']); $GLOBALS['wp_query'] =& new WP_Query(); return $GLOBALS['wp_query']->query($query); }

Vamos tentar adicionar outro loop para exibir os Posts de 'Serviços' adicionando as seguintes linhas sob o endwhile; do loop padrão atual.

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile;

E lá vai:

No entanto, há uma desvantagem para este método. Se tentarmos imprimir a categoria incluída no objeto de consulta, notamos que está alterada.

Tente inserir var_dump ( $wp_query->query_vars["category_name"] ); após a consulta de Serviços e atualize a página. Você deve ver este resultado:

 string(8) "services"

Isso aconteceu porque a consulta foi alterada, mas nunca revertida. Essa abordagem pode causar muitos problemas com o conteúdo que segue nossas consultas.

Para evitar esses conflitos e limpar após uma chamada para query_posts , faça uma chamada para wp_reset_query() , e a consulta principal original será restaurada. Então seu código deve ficar assim:

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

Ao atualizar sua página, você verá que a categoria da página inicial está de volta na consulta.

 string(10) "category-1"

Por fim, devemos mencionar que query_posts deve ser evitado, pois adiciona sobrecarga à sua consulta, pois na verdade faz com que a consulta principal seja executada novamente.

A função get_posts()

O mesmo resultado pode ser obtido com o uso da função get_posts() para recuperar uma matriz de postagens que correspondam aos critérios fornecidos.

Substitua o loop de serviços mostrado abaixo…

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

…com este:

 $my_query = get_posts( array ( 'category' => 17 ) ); foreach($my_query as $post) : setup_postdata($post); the_title( '<h4 class="example"></h4>' ); endforeach; var_dump ( $wp_query->query_vars["category_name"] );

Como você pode ver desta vez tivemos que trabalhar com o id da categoria ao invés do nome da categoria, de acordo com os argumentos get_posts() definidos pelo WordPress.

Outra coisa importante a ser observada aqui é que, embora não tenhamos redefinido a consulta, a saída var_dump da categoria de consulta ainda estava intacta e não foi alterada para 'services'. Isso porque get_posts() por si só não altera a consulta principal. Acabamos de usar uma nova variável ' $my_query ' para criar uma nova instância do objeto de consulta sem substituí-lo.

A função get_posts() usa os mesmos parâmetros que query_posts() e é sugerida para uso quando você deseja adicionar loops personalizados estáticos em qualquer lugar do seu modelo, pois é seguro e fácil de usar.

Criar um novo objeto WP_Query

$wp_query é um objeto da classe WP_Query e recupera o conteúdo do banco de dados necessário para a página atual. Substituir essa classe é nossa maneira de personalizar os resultados e exibir conteúdo diferente.

Este é o trecho de código que usaremos:

 $services_query = new WP_Query( 'category_name=services' ); if ( $services_query->have_posts() ) { while ( $services_query->have_posts() ) : $services_query->the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; } wp_reset_postdata(); var_dump ( $wp_query->query_vars["category_name"] );

Usamos o argumento 'category_name' para definir o slug da categoria que queremos que seus posts sejam exibidos.

Salvamos o novo objeto new WP_Query( 'category_name=services' ); na variável $services_query .

Em seguida, usamos um loop while para exibir o conteúdo e após isso redefinimos o loop com o wp_reset_postdata(); para restaurar os dados originais da consulta principal.

Se você quiser experimentar outros argumentos da classe WP_Query WordPress, você pode encontrar a lista completa em sua página do WordPress Codex.