¿Mostrar publicaciones relacionadas con otras publicaciones por un término de taxonomía?

2

Tengo un tipo de publicación personalizada para los perfiles de músico y una taxonomía para su ubicación (categorizada jerárquicamente en Países y luego en Ciudades). En las páginas de perfil individual del músico, necesito mostrar una lista de músicos en la misma ciudad (es decir, la taxonomía infantil). También sería bueno mostrar las publicaciones en el mismo país por separado (la taxonomía principal).

El problema parece ser recuperar la taxonomía de forma dinámica, separar las taxonomías principal y secundaria y utilizarlas en un nuevo bucle.

Puedo mostrar una lista de las taxonomías y eliminar los enlaces ...

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

... que devuelve un resultado como este: Nueva York, EE. UU.

Y puedo recorrer fácilmente las publicaciones por un valor de taxonomía fija ...

<?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; ?>

Pero estoy teniendo problemas al combinar los dos: por lo que puedo decir, 'get_the_term_list' no tiene la capacidad de devolver solo una taxonomía, y no parece haber una taxonomía equivalente a 'get_the_category'.

Cualquier ayuda muy apreciada !!!

    
pregunta George 06.10.2010 - 17:02

2 respuestas

9

Hola @George :

Según la cantidad de músicos que esperas tener en tu base de datos, puedes ir a la ruta completa de la API (que generalmente se prefiere, siempre que sea viable) si vas a tener un número grande de ellos (¿miles?) podría ir con algún SQL personalizado para extraer exactamente los registros que necesita.

Usando el enfoque de la API de WordPress

Los conceptos básicos del enfoque de WordPress API son llamar primero a wp_get_object_terms() con $post->ID de tu músico de perfil y tu taxonomía 'locations' , que devolverá una lista de objetos "term" . (Desafortunadamente, necesitas que sea solo una ubicación o esta solución se desmorona. Pero ignorando eso ...)

Luego, tome el ID de término del primer término y páselo más su taxonomía 'locations' a get_objects_in_term() , que devuelve una serie de ID de publicación que tienen los términos asociados para la taxonomía deseada. (Tenga en cuenta que esto incluirá TODAS publicaciones que tengan CUALQUIERA término asociado a su taxonomía 'locations' , por lo que este enfoque solo es válido para un número menor de registros .)

Luego creas un objeto WP_Query pasándole una consulta que usa post__in para filtrar por la lista de ID de músicos que recibió anteriormente, así como por su taxonomía 'locations' y su término específico de ciudad capturado para su músico perfilado. Por supuesto, también debes recordar filtrar el músico perfilado usando el argumento 'post__not_in' .

Tomados todos juntos, he empaquetado esa lógica en una función llamada get_posts_related_by_taxonomy() cuyo código fuente se puede ver aquí (omití algunos detalles cuando expliqué, pero espero que sean razonablemente obvios):

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;
}

Ahora puede usar esta función en su propio bucle así:

// 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 el enfoque de Direct SQL

Como ya dije, prefiero la API de WordPress cuando es viable. Desafortunadamente, creo que se encontrará con problemas de rendimiento o de memoria si tiene incluso un número razonable de músicos y utiliza el método que se muestra arriba.

Como alternativa eficiente y eficiente en memoria, puede usar SQL directo para reemplazar todo, incluyendo la llamada a get_objects_in_terms() en el ejemplo anterior. La buena noticia es que el SQL es sencillo y es poco probable que se encuentre con futuros problemas de compatibilidad con las nuevas versiones de WordPress, ya que el SQL solo utiliza referencias a claves primarias y externas y eso no cambiará a menos que renueven completamente el sistema de taxonomía, que creo que es poco probable.

Utilizando SQL, he creado una versión diferente de la función get_posts_related_by_taxonomy() , que la llamarás exactamente igual a como se llama la primera versión. El SQL reconoce que la tabla wp_term_relationships simplemente necesita estar unida por su campo común term_taxonomy_id que relacionará todos los registros de músicos para una ubicación determinada / (taxonomía) + ciudad / (término) par. Luego lo unimos a la tabla wp_term_taxonomy para que podamos filtrar en la taxonomía, y también filtramos por el músico perfilado en un extremo de la relación y filtramos para asegurarnos de que ninguno de los músicos relacionados sea el músico perfilado en el otro Fin de la relación. Finalmente, nos aseguramos de que los tipos de publicación de músicos relacionados sean iguales al tipo de publicación de nuestro músico perfilado para que pueda evitar una búsqueda más, en este caso, evitamos llamar a get_post() .

Nuestros resultados de SQL son una buena y simple matriz de ID de publicación que podemos usar nuevamente con el argumento post__in de WP_Query , pero esta vez no necesitamos incluir el post__not_in , taxonomy o term filter $args y podemos decirle a post_type que use 'any' ya que nuestra consulta SQL ya manejó todos esos.

Para la segunda versión, aquí está el código que necesita:

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);
}

Y nuevamente, usarás esta segunda versión de get_posts_related_by_taxonomy() exactamente de la misma manera que usaste la primera versión.

Espero que esto ayude!

    
respondido por el MikeSchinkel 07.10.2010 - 11:44
2

Consulte wp_get_object_terms() , es una función más general y lo que get_the_category() usa internamente.

    
respondido por el Rarst 06.10.2010 - 17:12

Lea otras preguntas en las etiquetas