özel gönderi türüne göre get_terms


19

İki özel gönderi türüm 'ülke' ve 'şehir' ve ortak bir sınıflandırma 'bayrağı' var.

Eğer kullanırsam:

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

Sınıflandırmadaki tüm terimlerin bir listesini alıyorum, ancak listeyi 'ülke' posta türüyle sınırlandırmak istiyorum.

Nasıl yapabilirim?


Yeni çözümü kullanma

<?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 yankılamıyorum. Neden?


Biraz daha net olabilir misin?
TheDeadMedic

Yanıtlar:


16

Korkarım bu doğal olarak mümkün değil (henüz?). Bu izi görün: http://core.trac.wordpress.org/ticket/18106

Sınıflandırma yönetici sayfasında da benzer şekilde gönderi sayısı tüm gönderi türlerini yansıtır . ( Bunun için de bir trac bileti olduğundan eminim ) http://core.trac.wordpress.org/ticket/14084

Ayrıca, bu ilgili gönderiye bakınız .


Yeni çözüm

Aşağıdakini yazdıktan sonra, çok daha iyi bir yol yayınladım (daha fazlasını yapabileceğiniz anlamına bağlı olarak) get_terms()çağrıda sağlanan filtreleri kullanmaktır . get_termsSQL sorgusunu değiştirmek için (posta türüne göre kısıtlamak için) bir filtre kullanan ve (koşullu olarak) bir sarmalayıcı işlevi oluşturabilirsiniz .

İşlev, ile aynı bağımsız değişkenleri alır get_terms($taxonomies, $args). $argsek argümanını post_typesalır ve bir dizi | string türünü alır.

Ama her şeyin 'beklendiği gibi' çalıştığını garanti edemem (sayımı doldurmayı düşünüyorum). Sadece varsayılan $argsfor kullanarak çalışır gibi görünüyor 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);           
}

kullanım

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

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

Orijinal çözüm

Yukarıdaki trak biletinden esinlenerek, (test edildi ve benim için çalışıyor)

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

kullanım

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

veya

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

Çalışıyor, ancak $ args'imle ne yapabilirim? Demek istediğim ... parent = 0 & orderby = name & hide_empty = 0
user1443216

hayır - bu bir dizi olması gerekir: $args = array('parent'=>0,'orderby'=>'name','hide_empty'=>0);. Sorgu dizelerine izin vermek için bunu düzenleyeceğim ...
Stephen Harris

$ Args'ımı şu örnekte nereye koyabilirim $terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));?
user1443216

Bunu yapamazsınız, sadece yeni çözümde:wpse57444_get_terms()
Stephen Harris

@ user1443216 $argsikinci argüman. İşte yeni koydunuzwpse57444_get_terms( 'flag', array( 'country', 'city' ) );
kaiser

2

@ stephen-harris'in cevabı benim için sadece kısmen çalıştı. Sayfada iki kez kullanmaya çalışırsam işe yaramadı. Ayrıca, mysql sorgularını gömme fikri beni endişelendiriyor - bir çözüm elde etmek, gelecekteki WP güncellemeleriyle çatışmaları önlemek için temel yöntemleri kullanmak için daha iyi bir uygulama olduğunu düşünüyorum. İşte benim çözümüm, referans aldığı Trac bileti hakkındaki 7 numaralı yoruma dayanarak

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

Kullanımı:

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

Bu sadece bir yazı tipi ve bir sınıflandırma için çalışır, çünkü ihtiyacım olan buydu, ancak bunu birden fazla değeri kabul etmek için değiştirmek çok zor olmazdı.

Bu Trac iş parçacığında bunun iyi ölçeklenemeyeceğine dair bazı sözler vardı, ancak oldukça küçük bir ölçekte çalışıyorum ve hızla ilgili herhangi bir sorun yaşamadım.


bu çözüm bana daha "yerli" görünüyor - neyse -> döngü "bitiş" hemen hemen sonra "wp_reset_postdata ()" çağırmalısınız: wordpress.stackexchange.com/questions/144343/…
Thomas Fellinger

2

İki özel gönderi türü 'ülke' ve 'şehir' ve paylaşılan bir sınıflandırma 'bayrağı'. Listeyi gönderi türü 'ülke' ile sınırlamak istiyorsunuz.

İşte daha basit bir çözüm:

$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

Stephen Harris'in mükemmel cevabı hakkında bir yorum.

Bunun gibi birden fazla yayın türüyle kullanıldığında herhangi bir terim döndürmez $flags = wpse57444_get_terms('flags', array('post_types' => array('country','city')));. Bunun nedeni, $ wpdb-> ready komutunun $ post_types_str dizesini p.post_type IN('country,city')olması gerektiği gibi sterilize etmesidir p.post_type IN('country','city'). Bu bileti görün: 11102 . Bu sorunu çözmek için bu konudaki çözümü kullanın: /programming//a/10634225


1

Ayrıca @Stephen Harris'in cevabını kullanmaya çalıştım, ancak ihtiyacım olan sorgu tek bir sorgu olarak ve filtre parçalarını kullanarak yazmak oldukça zordu.

Ayrıca, bu işlevi aynı sayfada birden çok kez kullanmam gerekiyordu ve wpse_filter_terms_by_cptişlevi sarma işlevinin dışında bildirme sorununu çözdüm .

Her neyse @ Mark Pruce'un cevabı bana göre, wp_get_object_termsfonksiyon için argümanları hazırlamak için bir tane daha sorgu (ve ilgili döngü) yapmanız gerekmesine rağmen, aynı nedenlerle daha iyi uyuyor .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.