カスタム投稿タイプ別get_terms


19

「国」と「都市」の2つのカスタム投稿タイプと、共有分類「フラグ」があります。

私が使用する場合:

<?php $flags = get_terms('flag', 'orderby=name&hide_empty=0');

分類法のすべての用語のリストを取得しますが、リストを投稿タイプ「国」に制限します。

どうすればいいですか?


新しいソリューションを使用する

<?php 
$flags = wpse57444_get_terms('flags',array('parent' => 0,'hide_empty' => 1,'post_types' =>array('country')));
foreach ($flags as $flag) {
    $childTerms = wpse57444_get_terms('flags',array('parent' => $flag->term_id,'hide_empty' => 1,'post_types' =>array('country')));
    foreach ($childTerms as $childTerm) {
        echo $childTerm->name.'<br />';
    }
}
?>

$ childTerm-> nameをエコーできません。どうして?


もう少しはっきりさせていただけますか?
TheDeadMedic

回答:


16

これはネイティブでは不可能だと思う(まだ?)。 このトラックを参照してください: http //core.trac.wordpress.org/ticket/18106

同様に、分類管理ページでは、投稿数はすべての投稿タイプを反映しています。(そのためのtracチケットもあると確信しています http://core.trac.wordpress.org/ticket/14084

こちらの関連​​記事もご覧ください


新しいソリューション

以下のコードを書いたので、get_terms()呼び出しで提供されたフィルターを使用するのがはるかに良い方法をリリースしました(さらに多くのことができるという意味では)。使用するラッパー関数を作成できますget_termsフィルターをして(条件付きで)SQLクエリを操作する(投稿タイプによって制限する)フィルターを追加。

関数はと同じ引数を取りますget_terms($taxonomies, $args)$args追加の引数を取り、その引数post_typesは投稿タイプの配列|文字列を取ります。

しかし、私はすべてが「期待どおり」に機能することを保証することはできません(カウントを埋めることを考えています)。デフォルトの$argsfor を使用して動作するように見えますget_terms

function wpse57444_get_terms( $taxonomies, $args=array() ){
    //Parse $args in case its a query string.
    $args = wp_parse_args($args);

    if( !empty($args['post_types']) ){
        $args['post_types'] = (array) $args['post_types'];
        add_filter( 'terms_clauses','wpse_filter_terms_by_cpt',10,3);

        function wpse_filter_terms_by_cpt( $pieces, $tax, $args){
            global $wpdb;

            // Don't use db count
            $pieces['fields'] .=", COUNT(*) " ;

            //Join extra tables to restrict by post type.
            $pieces['join'] .=" INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id 
                                INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id ";

            // Restrict by post type and Group by term_id for COUNTing.
            $post_types_str = implode(',',$args['post_types']);
            $pieces['where'].= $wpdb->prepare(" AND p.post_type IN(%s) GROUP BY t.term_id", $post_types_str);

            remove_filter( current_filter(), __FUNCTION__ );
            return $pieces;
        }
    } // endif post_types set

    return get_terms($taxonomies, $args);           
}

使用法

$args =array(
    'hide_empty' => 0,
    'post_types' =>array('country','city'),
);

$terms = wpse57444_get_terms('flag',$args);

オリジナルの回避策

上記のtracチケットからインスピレーションを得た(テスト済みで、私にとってはうまくいく)

function wpse57444_filter_terms_by_cpt($taxonomy, $post_types=array() ){
    global $wpdb;

    $post_types=(array) $post_types;
    $key = 'wpse_terms'.md5($taxonomy.serialize($post_types));
    $results = wp_cache_get($key);

    if ( false === $results ) {
       $where =" WHERE 1=1";
       if( !empty($post_types) ){
            $post_types_str = implode(',',$post_types);
            $where.= $wpdb->prepare(" AND p.post_type IN(%s)", $post_types_str);
       }

       $where .= $wpdb->prepare(" AND tt.taxonomy = %s",$taxonomy);

       $query = "
          SELECT t.*, COUNT(*) 
          FROM $wpdb->terms AS t 
          INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id 
          INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id 
          INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id 
          $where
          GROUP BY t.term_id";

       $results = $wpdb->get_results( $query );
       wp_cache_set( $key, $results );
    }        

    return $results;
}

使用法

 $terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));

または

 $terms = wpse57444_filter_terms_by_cpt('flag','country');

動作しますが、$ argsで何ができますか?つまり... parent = 0&orderby = name&hide_empty = 0
user1443216

no-これは配列でなければなりません:$args = array('parent'=>0,'orderby'=>'name','hide_empty'=>0);。私は、クエリ文字列を許可するように、これを編集します...
スティーブン・ハリス

この例の$ argsはどこに置け$terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));ますか?
user1443216

あなたはその1で、唯一の新しいソリューションにすることはできません:wpse57444_get_terms()
スティーブン・ハリス

@ user1443216 $argsは2番目の引数です。そこにあなたが置くwpse57444_get_terms( 'flag', array( 'country', 'city' ) );
kaiser

2

上記の@ stephen-harrisの答えは部分的にしか機能しませんでした。ページで2回使用しようとしても、機能しませんでした。また、そのようなmysqlクエリを埋めるという考えは心配です。将来のWP更新との競合を避けるために、コアメソッドを使用してソリューションを達成する方が良いと思います。ここに彼が参照するTracチケットに関するコメント#7に基づく私の解決策があります

function get_terms_by_custom_post_type( $post_type, $taxonomy ){
  $args = array( 'post_type' => $post_type);
  $loop = new WP_Query( $args );
  $postids = array();
  // build an array of post IDs
  while ( $loop->have_posts() ) : $loop->the_post();
    array_push($postids, get_the_ID());
  endwhile;
  // get taxonomy values based on array of IDs
  $regions = wp_get_object_terms( $postids,  $taxonomy );
  return $regions;
}

使用法:

$terms = get_terms_by_custom_post_type('country','flag');

これは1つの投稿タイプと1つの分類に対してのみ機能します。これが必要なことですが、これを変更して複数の値を受け入れることはそれほど難しくありません。

そのTracスレッドには、これがうまくスケールしないかもしれないといういくつかの言及がありましたが、私はかなり小さなスケールで作業しており、速度に問題はありませんでした。


MEEに、このソリューションは、ルックスより「ネイティブ」 -とにかく- >あなたが右のループの「ENDWHILE」後「wp_reset_postdata()」を呼び出す必要があります。wordpress.stackexchange.com/questions/144343/...
トーマスFellinger

2

2つのカスタム投稿タイプ「国」と「市」、および共有分類「フラグ」。リストを投稿タイプ「国」に制限します。

より簡単なソリューションを次に示します。

$posts_in_post_type = get_posts( array(
    'fields' => 'ids',
    'post_type' => 'country',
    'posts_per_page' => -1,
) );
$terms = wp_get_object_terms( $posts_in_post_type, 'flag', array( 'ids' ) ); ?>

1

[編集]これは、スティーブン・ハリスによる優れた答えに対するコメントです。

このような複数の投稿タイプで使用した場合、用語は返されません$flags = wpse57444_get_terms('flags', array('post_types' => array('country','city')));。これは、$ wpdb-> prepareが$ post_types_str文字列をサニタイズp.post_type IN('country,city')するためp.post_type IN('country','city')です。このチケット11102を参照してください。これを回避するには、このトピックのソリューションを使用してくださいhttps : //stackoverflow.com/a/10634225


1

また、@ Stephen Harrisの回答を使用しようとしましたが、必要なクエリを単一のクエリとして作成し、フィルタ部分を使用するのは非常に困難でした。

さらに、同じページでその関数を複数回使用する必要がありwpse_filter_terms_by_cpt、ラッパー関数の外側で関数を宣言する問題を解決しました。

とにかく、@ Mark Pruceの私の意見では、wp_get_object_terms関数の引数を準備するためにもう1つのクエリ(および関連するループ)を作成する必要があるにもかかわらず、彼が言ったのと同じ理由でより適切です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.