get_terms berdasarkan jenis posting khusus

19

Saya memiliki dua jenis pos kustom 'negara' dan 'kota' dan 'bendera' taksonomi bersama.

Jika saya menggunakan:

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

Saya mendapatkan daftar semua istilah dalam taksonomi, tetapi saya ingin membatasi daftar untuk jenis tulisan 'negara'.

Bagaimana saya bisa melakukannya?


Menggunakan solusi baru

<?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 />';
    }
}
?>

Saya tidak dapat mengulangi $ childTerm-> nama. Mengapa?

pengguna1443216
sumber
Bisakah Anda menjadi sedikit lebih jelas?
TheDeadMedic

Jawaban:

16

Saya khawatir ini tidak mungkin dilakukan secara asli (belum?). Lihat trac ini: http://core.trac.wordpress.org/ticket/18106

Demikian pula pada halaman admin taksonomi jumlah posting mencerminkan semua jenis posting. ( Saya cukup yakin ada tiket trac untuk itu juga ) http://core.trac.wordpress.org/ticket/14084

Lihat juga, posting terkait ini .


Solusi baru

Setelah menulis yang di bawah ini, saya telah merilis cara yang lebih baik (alteast dalam arti bahwa Anda dapat melakukan lebih banyak) adalah dengan menggunakan filter yang disediakan dalam get_terms()panggilan. Anda dapat membuat fungsi pembungkus yang menggunakan get_termsdan (secara kondisional) menambahkan filter untuk memanipulasi kueri SQL (untuk membatasi menurut jenis posting).

Fungsi ini mengambil argumen yang sama dengan get_terms($taxonomies, $args). $argsmengambil argumen tambahan post_typesyang membutuhkan array | string tipe posting.

Tetapi saya tidak dapat menjamin bahwa semuanya berfungsi 'seperti yang diharapkan' (saya berpikir untuk menghitungnya). Tampaknya berfungsi hanya dengan default $argsuntuk 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);           
}

Pemakaian

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

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

Bekerja di sekitar

Terinspirasi dari tiket trac di atas, (diuji, dan berhasil untuk saya)

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

Pemakaian

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

atau

 $terms = wpse57444_filter_terms_by_cpt('flag','country');
Stephen Harris
sumber
Itu bekerja, tetapi apa yang bisa saya lakukan dengan $ args saya? Maksud saya ... parent = 0 & orderby = name & hide_empty = 0
user1443216
tidak ada - ini harus menjadi array: $args = array('parent'=>0,'orderby'=>'name','hide_empty'=>0);. Saya akan mengedit ini untuk mengizinkan string permintaan ...
Stephen Harris
Dimana saya dapat menempatkan $ args saya dalam contoh ini: $terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));?
user1443216
Anda tidak bisa dalam yang itu, hanya dalam solusi baru:wpse57444_get_terms()
Stephen Harris
@ user1443216 $argsadalah argumen kedua. Di sana Anda baru saja meletakkanwpse57444_get_terms( 'flag', array( 'country', 'city' ) );
kaiser
2

@ stephen-harris jawaban di atas hanya bekerja untuk saya sebagian. Jika saya mencoba menggunakannya dua kali pada halaman, itu tidak berhasil. Juga, gagasan untuk mengubur pertanyaan mysql seperti itu membuat saya khawatir - saya pikir praktik yang lebih baik untuk menggunakan metode inti untuk mencapai solusi, untuk menghindari konflik dengan pembaruan WP di masa depan. Ini solusi saya, berdasarkan beberapa komentar # 7 di tiket Trac yang dia referensikan

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

Pemakaian:

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

Ini hanya berfungsi untuk satu jenis posting dan satu taksonomi, karena itulah yang saya butuhkan, tetapi tidak akan terlalu sulit untuk memodifikasi ini untuk menerima beberapa nilai.

Ada beberapa yang menyebutkan pada thread Trac bahwa ini mungkin tidak skala dengan baik, tapi saya sedang bekerja pada skala yang cukup kecil dan tidak memiliki masalah dengan kecepatan.

Tandai Pruce
sumber
solusi ini terlihat lebih "asli" untuk saya - bagaimanapun -> Anda harus memanggil "wp_reset_postdata ()" tepat setelah "endwhile" dari loop: wordpress.stackexchange.com/questions/144343/…
Thomas Fellinger
2

Dua jenis pos kustom 'negara' dan 'kota' dan 'bendera' taksonomi bersama. Anda ingin membatasi daftar ke jenis posting 'negara'.

Ini solusi yang lebih sederhana:

$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' ) ); ?>
Alex
sumber
1

[Sunting] Ini adalah komentar pada jawaban yang sangat baik oleh Stephen Harris.

Itu tidak mengembalikan istilah apa pun jika digunakan dengan beberapa jenis posting seperti ini $flags = wpse57444_get_terms('flags', array('post_types' => array('country','city')));. Ini karena $ wpdb-> ready membersihkan string $ post_types_str p.post_type IN('country,city')ketika seharusnya p.post_type IN('country','city'). Lihat tiket ini: 11102 . Gunakan solusi dari topik ini untuk menyiasatinya: /programming//a/10634225

keesiemeijer
sumber
1

Saya juga mencoba menggunakan jawaban @Stephen Harris, tetapi permintaan yang saya butuhkan cukup sulit untuk ditulis sebagai satu permintaan dan menggunakan potongan filter.

Selain itu, saya juga perlu menggunakan fungsi itu beberapa kali di halaman yang sama dan saya memecahkan masalah dengan mendeklarasikan wpse_filter_terms_by_cptfungsi di luar fungsi wrapper.

Anyways @Mark Pruce menjawab menurut saya lebih cocok, untuk alasan yang sama katanya, meskipun perlu Anda membuat satu permintaan lagi (dan loop terkait) untuk menyiapkan argumen untuk wp_get_object_termsfungsi.

Sgaddo
sumber