Exibindo postagens relacionadas a outras postagens por um termo de taxonomia?

2

Eu tenho um tipo de post personalizado para os perfis dos músicos e uma taxonomia para sua localização (categorizada hierarquicamente em Countries e depois em Cities). Nas páginas de perfil individual do músico, preciso exibir uma lista de músicos na mesma cidade (ou seja, a taxonomia infantil). Também seria bom exibir posts no mesmo país separadamente (a taxonomia pai).

O problema parece ser recuperar a taxonomia dinamicamente, separando as taxonomias pai e filho e usando-as em um novo loop.

Eu posso exibir uma lista das taxonomias e remover os links ...

$terms = get_the_term_list( $post->ID, 'locations', '', ', ', '' ) ;
echo strip_tags($terms);

... que retorna um resultado como este: Nova York, EUA

E posso percorrer facilmente as postagens por um valor fixo de taxonomia ...

<?php $my_query = new WP_Query( array( 'locations' => 'new-york', 'showposts' => 10 ) ); ?>
<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; ?>

Mas estou tendo problemas em combinar os dois: Tanto quanto eu posso dizer 'get_the_term_list' não tem a capacidade de retornar apenas uma taxonomia, e não parece haver um equivalente taxonomia de 'get_the_category'.

Qualquer ajuda muito apreciada !!!

    
por George 06.10.2010 / 17:02

2 respostas

9

Oi @George :

Dependendo do número de músicos que você espera ter em seu banco de dados, você pode usar a rota completa da API (que geralmente é preferível, sempre que for viável) se você tiver um grande número deles (milhares?) você poderia ir com algum SQL personalizado para extrair exatamente os registros que você precisa.

Usando a abordagem da API do WordPress

O básico da abordagem da API do WordPress é primeiro chamar wp_get_object_terms() com $post->ID do seu perfil musical e seu 'locations' taxonomia que retornará uma lista de objetos "termo" . (Infelizmente você precisa que seja apenas um local ou esta solução se desfaz. Mas ignorar isso ...)

Em seguida, pegue o termo ID do primeiro termo e passe-o mais sua 'locations' taxonomy para get_objects_in_term() , que retorna uma matriz de IDs de postagem com os termos associados à taxonomia desejada. (observe que isso incluirá TODAS postagens que têm QUALQUER termo associado à sua 'locations' taxonomia, e é por isso que essa abordagem é válida apenas para um número menor de registros .)

Em seguida, você cria um objeto WP_Query transmitindo a ele uma consulta que usa post__in para filtrar pela lista de IDs de músico que você recebeu acima, bem como pela sua 'locations' taxonomy e seu termo de cidade específico capturado para seu músico com perfil. É claro que você também deve se lembrar de filtrar o músico usando o argumento 'post__not_in' .

Considerados todos juntos, empacotei essa lógica em uma função chamada get_posts_related_by_taxonomy() cujo código fonte você pode ver aqui (deixei de fora alguns detalhes quando expliquei, mas espero que sejam razoavelmente óbvios):

function get_posts_related_by_taxonomy($post_id,$taxonomy,$args=array()) {
  $query = new WP_Query();
  $terms = wp_get_object_terms($post_id,$taxonomy);
  if (count($terms)) {
    // Assumes only one term for per post in this taxonomy
    $post_ids = get_objects_in_term($terms[0]->term_id,$taxonomy);
    $post = get_post($post_id);
    $args = wp_parse_args($args,array(
      'post_type' => $post->post_type, // The assumes the post types match
      'post__in' => $post_ids,
      'post__not_in' => $post->ID,
      'taxonomy' => $taxonomy,
      'term' => $terms[0]->slug,
    ));
    $query = new WP_Query($args);
  }
  return $query;
}

Agora você pode usar essa função em seu próprio loop da seguinte forma:

// This assumes that your musician profile record is in the $post variable
$musicians = get_posts_related_by_taxonomy($post->ID,'locations');?>
<ul>
<?php while ($musicians->have_posts()): $musicians->the_post(); ?>
  <li><?php the_id(); ?> -- <?php the_title(); ?></li>
<?php endwhile; ?>
</ul>

Usando a abordagem Direct SQL

Como eu já disse, prefiro a API do WordPress quando é viável. Infelizmente, acho que você terá problemas de desempenho ou memória se tiver um número razoavelmente grande de músicos e usar a abordagem mostrada acima.

Como alternativa eficiente em termos de desempenho e memória, você pode usar SQL direto para substituir tudo até e incluindo a chamada para get_objects_in_terms() no exemplo anterior. A boa notícia é que o SQL é direto e dificilmente se deparará com problemas futuros de compatibilidade com novas versões do WordPress, já que o SQL usado apenas faz referência a chaves primárias e estrangeiras e isso não mudará, a menos que eles reformulem completamente o sistema de taxonomia, que eu acho improvável.

Usando o SQL, criei uma versão diferente da função get_posts_related_by_taxonomy() , a qual você a chamará exatamente como a primeira versão é chamada. O SQL reconhece que a tabela wp_term_relationships simplesmente precisa ser unida pelo seu campo comum term_taxonomy_id que relacionará todos os registros do músico para um dado local / (taxonomia) + cidade / par (termo) . Então nos juntamos à tabela wp_term_taxonomy para que possamos filtrar a taxonomia, e também filtramos pelo músico perfilado em uma extremidade do relacionamento e filtramos para garantir que nenhum dos músicos relacionados seja o músico analisado na outra fim do relacionamento. Nós finalmente nos certificamos de que os músicos relacionados a postar tipos são iguais ao tipo de post de nosso músico analisado, então você pode evitar mais uma busca, nesse caso evitamos chamar get_post() .

Nossos resultados do SQL são um bom e simples conjunto de IDs de postagem que podemos usar novamente com o argumento post__in de WP_Query , mas desta vez não precisamos incluir o post__not_in , taxonomy ou term filter $args e podemos informar post_type para usar 'any' , pois nossa consulta SQL já tratou de todos eles.

Para a segunda versão, aqui está o código que você precisa:

function get_posts_related_by_taxonomy($post_id,$taxonomy,$args=array()) {
  global $wpdb;
  $sql =<<<SQL
SELECT
  related.object_id
FROM
  {$wpdb->term_relationships} post
  INNER JOIN {$wpdb->term_taxonomy} link ON post.term_taxonomy_id = link.term_taxonomy_id
  INNER JOIN {$wpdb->term_relationships} related ON post.term_taxonomy_id = related.term_taxonomy_id
WHERE 1=1
  AND link.taxonomy='%s'
  AND post.object_id=%d
  AND post.object_id<>related.object_id
  AND post.post_type==related.post_type
SQL;
  $post_ids = $wpdb->get_col($wpdb->prepare($sql,$taxonomy,$post_id));
  $args = wp_parse_args($args,array(
    'post_type' => 'any',
    'post__in' => $post_ids,
  ));
  return new WP_Query($args);
}

E, novamente, você usará essa segunda versão de get_posts_related_by_taxonomy() exatamente da mesma maneira que usou a primeira versão.

Espero que isso ajude!

    
por MikeSchinkel 07.10.2010 / 11:44
2

Confira wp_get_object_terms() , é uma função mais geral e o que get_the_category() usa internamente.

    
por Rarst 06.10.2010 / 17:12