Loops personalizados no WordPress

Em muitas situações precisamos modificar a query natural do WordPress, para eliminar categorias ou posts da listagem, para exibir um tipo de post específico, enfim para várias finalidades. Se você quer, por exemplo, listar apenas posts das categorias 2 e 6 ou esconder os psts da categoria 15… não há um link natural para essas listas, é preciso criar loops personalizados.

Bem, na verdade seria possível fazer isso usando hooks como ‘posts_where’, ‘posts_join’ ou ‘posts_selection’ para modificar a requisição antes de enviá-la ao MySQL. Mas vamos aqui usar um outro método que consiste em modificar as variáveis que vão formar essa requisição e que estão armazenadas no array $wp_query->query_vars. Esse é o método mais utilizado por ser o mais simples. Vejamos alguns exemplos.

O mais básico seria colocar  algo como isso diretamente num arquivo do seu tema:

// para colocar na prática os exemplos acima
query_posts('cat=2,6');
// ou
query_posts('cat=-15');

Mas fazer assim tem dois incovenientes.

  1. Primeiro que como nesse ponto do processamento a query já estava pronta e forçamos o sistema a fazer tudo duas vezes, jogando fora todo o primeiro esforço (e tempo)
  2. Segundo que ao inicializar uma nova query mandando apenas o parâmetro ‘cat’, eliminamos todas as outras variáveis, que assumem seus valores padrão, entre elas a ‘paged’, que informa a página atual (e que retorna ao valor 1 – digo isso porque este é o problema mais facilmente identificável – a paginação deixa de funcionar).

Para corrigir os problemas, começamos usando um hook, um gancho que vai nos permitir executar nosso código no momento correto do processamento. O hook que buscamos é o ‘pre_get_posts’ que é disparado imediatamente antes da query ser preparada. E como ainda não aconteceu, não precisamos forçar uma nova query, apenas mudar as variáveis e deixar o processamento seguir seu curso.

function my_remove_cat() {
global $wp_query;
$wp_query->query_vars['category__not_in'] = array(15,32);
// o que é equivalente a
$wp_query->query_vars['cat'] = '-15,-32';
}
add_action('pre_get_posts', 'my_remove_cat');

Tá, mas e se não der pra usar o hook? se tivermos que fazer isso diretamente de uma page template, por exemplo?

Bem, num caso assim, o que foi considerado “um problema” passa a ser um mal necessário e ignoramos o fato de nesse ponto a query já estar pronta. Refazemos a query usando query_posts().

O código deve estar antes do início do loop. Repare que enviamos para query_posts() as mesmas variáveis que já definidas, com seus valores inalterados, menos a ‘category__not_in’, que modificamos.

/*
Template name: Teste
*/
global $wp_query;
$wp_query->query_vars['category__not_in'] = array(15,32);
query_posts($wp_query->query_vars);

É simples, não? Entendido isso, vou mostrar uma funçãozinha que uso para definir query_vars e que facilita um pouco esse já pouco trabalho (sou um preguiçoso confesso).

function my_query_set($var, $val = '', $qp = false) {
  global $wp_query;
  if(is_array($var) && empty($val)) {
    foreach($var as $n => $v) {
      if(is_string($n)) $wp_query->set($n, $v);
    }
  } else $wp_query->set($var, $val);
  if($qp) query_posts($wp_query->query_vars);
}

// modos de usar:
// reproduzindo os ex. acima
// .................

function my_remove_cat() {
my_query_set('category__not_in', array(15,32));
}
add_action('pre_get_posts', 'my_remove_cat');

// .................

/*
Template name: Teste
*/
my_query_set('category__not_in', array(15,32), true); // chamando query_posts()

// .................

// podemos enviar arrays para definir vários valores numa vez só
$props = array(
  'category__not_in' => array(15,32),
  'post_type' => array('post','page')
);

my_query_set($props);
// ou
my_query_set($props, '', true); // chamando query_posts()

A julgar pelo tempo que eu levei para entender isso aí, imagino (espero) que possa ser útil para os iniciantes na construção de plugins para o WP.

Posts Similares

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

5 Comentários

  1. Olá cau, artigo esclarecedor, parabéns! Estou desenvolvendo um portal e talvez possa me auxiliar em uma dúvida.
    Esse portal que estarei desenvolvendo servirá de consulta para empresas da minha região. Dessa forma no banco de dados do wordpress inseri campos novos na tabela wp_posts com os nomes (empresa, endereço e telefone), gostaria que os dados que estão dentro desses novos campos fossem inseridos nos seus respectivos posts. Poderia me ajudar?

    Obrigado

  2. Fala Gustavo
    cara, acredito que você escolheu o método menos indicado de adicionar valores ao banco… se for mesmo mexer na organização da database, crie uma tabela pra vc. Mas eu recomendo usar os meta campos dos posts. use update_post_meta(post-id, nome, valor) ao salvar o post (use o hook ‘save_post’ – se não me engano).

  3. Olá Cau,
    Gostaria de saber como faz para inserir tópicos recentes dentro de um post, assim como você fez no fim deste post no "Leia também:"
    Fico no aguardo
    Obrigado.

  4. Olá Cau,
    eu queria coloca slide em todas as categorias, mas da conflito seu eu colocar o loop do slide primeiro, eo loop dos posts, aparece loop do slide no loop dos posts, poderia me ajuda serei grato!