是否按分类术语显示与其他帖子相关的帖子?

时间:2010-10-06 作者:George

我有一个音乐家个人资料的自定义帖子类型,以及他们所在位置的分类法(按照国家和城市的等级划分)。在音乐家个人档案页面上,我需要显示同一城市的音乐家列表(即儿童分类法)。单独显示同一个国家的帖子也很好(父分类法)。

问题似乎是动态检索分类法,分离父分类法和子分类法,并在新的循环中使用它们。

我可以显示分类法列表,并删除链接。。。

$terms = get_the_term_list( $post->ID, \'locations\', \'\', \', \', \'\' ) ;
echo strip_tags($terms);
。。。返回如下结果:美国纽约

我可以通过一个固定的分类值轻松地遍历帖子。。。

<?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; ?>
但我在将两者结合起来时遇到了问题:据我所知,“get\\u the\\u term\\u list”不能只返回一个分类法,而且似乎没有一个与“get\\u the\\u category”相当的分类法。

非常感谢您的帮助!!!

2 个回复
SO网友:MikeSchinkel

你好@George:

根据您的数据库中预计有多少音乐家,如果您想要拥有大量音乐家(数千?),您可以选择完整的API路线(这通常是首选的,只要可行)您可以使用一些自定义SQL来精确地提取所需的记录。

使用WordPress API方法,WordPress API方法的基础是首先调用wp_get_object_terms() 具有$post->ID 您的个人资料音乐家和\'locations\' 将返回对象列表的分类法(不幸的是,您需要它仅位于一个位置,否则此解决方案将崩溃。但忽略此…)

接下来,您获取第一个学期的学期ID,并将其与您的\'locations\' 分类法到get_objects_in_term() 它返回一个post ID数组,其中包含与所需分类相关联的术语(注意这将包括ALL 具有ANY 与您的\'locations\' 分类法,这就是为什么这种方法只适用于少数记录。)

然后创建一个WP_Query 对象向其传递一个使用post__in 按您在上面收到的音乐家ID列表以及您的\'locations\' 分类法及其特定的城市术语是为您的个人资料音乐家捕获的。当然,您还必须记住使用\'post__not_in\' 论点

综上所述,我将该逻辑打包为一个函数,名为get_posts_related_by_taxonomy() 您可以在这里看到其源代码(我在解释时省略了一些细节,但希望它们相当明显):

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;
}
现在您可以在中使用此函数your own loop 像这样:

// 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>
使用直接SQL方法正如我已经说过的,如果可行的话,我更喜欢WordPress API。不幸的是,我认为如果你有相当多的音乐家,并且使用上面所示的方法,你会遇到演奏或记忆问题。

作为一种性能和内存高效的替代方法,您可以使用直接SQL来替换调用get_objects_in_terms() 在前面的示例中。好消息是,SQL很简单,不太可能在将来遇到新版本WordPress的兼容性问题,因为SQL只引用主键和外键,除非它们彻底修改分类系统,否则不会改变,我认为这是不可能的。

使用SQL,我创建了get_posts_related_by_taxonomy() 调用与第一个版本完全相同的函数。SQL识别表wp_term_relationships 只是需要通过共同的term_taxonomy_id 字段,该字段将关联给定位置的所有音乐家记录//em>(分类法)+城市//em>(术语)对。然后我们把它加入wp_term_taxonomy 表,以便我们可以在分类法上进行筛选,我们还可以按关系一端的已配置音乐家进行筛选,并进行筛选以确保没有任何相关音乐家是关系另一端的已配置音乐家。我们最终确保相关的音乐家帖子类型与我们分析的音乐家帖子类型相同,这样您就可以避免再次查找,在这种情况下,我们避免调用get_post().

我们从SQL得到的结果是一个简单的post ID数组,我们可以再次使用post__in 争论WP_Query 但这次我们不需要包括post__not_in, taxonomyterm 滤器$args 我们可以知道post_type 使用\'any\' 因为我们的SQL查询已经处理了所有这些。

对于第二个版本,以下是您需要的代码:

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);
}
同样,您将使用get_posts_related_by_taxonomy() 与您使用第一个版本的方式完全相同。

希望这有帮助!

SO网友:Rarst

退房wp_get_object_terms(), 更一般的功能是什么get_the_category() 内部使用。

结束

相关推荐