web-dev-qa-db-ja.com

分類用語による他の投稿に関連する投稿の表示

私はミュージシャンのプロフィールのためのカスタム投稿タイプと、それらの場所のための分類法を持っています(階層的に国とそれから都市に分類されます)。ミュージシャンの個々のプロフィールページに、私は同じ都市のミュージシャンのリストを表示する必要があります(すなわち、子供の分類法)。同じ国の投稿を別々に表示するのもよいでしょう(親の分類法)。

問題は、分類法を動的に取得し、親と子の分類法を分離し、それらを新しいループで使用することにあるようです。

分類法のリストを表示し、リンクを削除することができます。

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

しかし、私は2つを組み合わせることに問題があります。 'get_the_term_list'には1つの分類のみを返す機能はなく、 'get_the_category'と同等の分類はないようです。

任意の助け大いに感謝します!

2
George

こんにちは@ジョージ

データベースに何人のミュージシャンがいることを期待しているかに応じて、フルAPIルートを使用することができます(それが実現可能な場合は常に推奨されます)。そのうちの(数千?)あなたは正確にあなたが必要とするレコードを引き出すためにいくつかのカスタムSQLを使うことができます。

WordPress APIアプローチを使用する

WordPress APIアプローチの基本は、まずプロフィールミュージシャンの$post->ID "term"オブジェクトのリストを返す'locations'分類法でwp_get_object_terms()を呼び出すことです。 (残念ながら、1つの場所にする必要があります。そうしないと、この解決策は崩れますが、それを無視すると...)

次に、最初の用語の用語IDを取得し、それに加えて'locations'分類をget_objects_in_term()に渡します。これにより、目的の分類に関連付けられた用語を持つ投稿IDの配列が返されます。 (注これには、あなたの'locations'分類法からANYという用語が関連付けられたすべて投稿が含まれます。これが、このアプローチが少数のレコードに対してのみ有効な理由です。)

次に、ミュージシャンのリストでフィルタリングするために WP_Query を使用するクエリを渡すpost__inオブジェクトを作成します。あなたの'locations'分類法およびあなたのプロファイルされたミュージシャンのために捕獲されたその特定の都市用語によって、あなたが上記で受け取ったID。もちろん、'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;
}

この関数は、 独自のループ で次のように使用します。

// 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は参照キーと外部キーのみを使用しており、分類システムを完全に改良しない限り変更されないため、SQLは単純明快で新しいバージョンのWordPressとの将来的な互換性の問題に遭遇する可能性は低いです。ありそうもない。

SQLを使用して、私はget_posts_related_by_taxonomy()関数の異なるバージョンを作成しました。あなたはそれをあなたが最初のバージョンが呼ばれるのと全く同じように呼ぶでしょう。 SQLは、テーブルwp_term_relationshipsは、与えられた場所のすべてのミュージシャンレコードを関連づける共通のterm_taxonomy_idフィールドによって単純に結合される必要があることを認識しています/(分類法)+ city /(term)ペア次に、それをwp_term_taxonomyテーブルに結合して分類法でフィルタリングできるようにします。また、関係の一方の端ではプロファイルドミュージシャンでフィルタリングし、もう一方の端ではプロファイルドミュージシャンでないことを確認します。関係。関連するミュージシャンの投稿タイプが、プロファイルされたミュージシャンの投稿タイプと同じであることを確認したので、もう1回検索を避けることができます。この場合はget_post()を呼び出さないようにします。

SQLからの結果は、post__inWP_Query引数で再び使用できる素敵な単純な投稿IDの配列ですが、今度はpost__not_intaxonomy、またはtermフィルター$argsを含める必要はなく、post_type'any'を使用するよう指示私たちのSQLクエリはすでにそれらすべてを処理しています。

2番目のバージョンでは、これが必要なコードです。

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()のこの2番目のバージョンも、最初のバージョンとまったく同じ方法で使用します。

お役に立てれば!

9
MikeSchinkel

wp_get_object_terms() を調べてください。これはより一般的な関数であり、get_the_category()が内部で使用しているものです。

2
Rarst