get_terms ตามประเภทโพสต์ที่กำหนดเอง


19

ฉันมี 'ประเทศ' และ 'เมือง' ของโพสต์แบบกำหนดเองสองแบบและ 'tax' แบบ taxonomy ที่แชร์

ถ้าฉันใช้:

<?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-> ทำไม?


คุณชัดเจนขึ้นหน่อยได้ไหม
TheDeadMedic

คำตอบ:


16

ฉันเกรงว่าสิ่งนี้จะไม่สามารถเกิดขึ้นได้ ดู trac นี้: http://core.trac.wordpress.org/ticket/18106

ในทำนองเดียวกันในหน้าผู้ดูแลระบบภาษีการนับโพสต์แสดงถึงประเภทโพสต์ทั้งหมด ( ฉันค่อนข้างมั่นใจว่ามีตั๋ว trac ด้วยเช่นกัน ) http://core.trac.wordpress.org/ticket/14084

ดูเพิ่มเติมโพสต์ที่เกี่ยวข้องนี้


โซลูชั่นใหม่

เมื่อเขียนข้างล่างนี้ฉันได้เปิดตัววิธีที่ดีกว่ามาก (ในแง่ที่คุณสามารถทำได้มากขึ้น) คือการใช้ตัวกรองที่มีให้ในการget_terms()โทร คุณสามารถสร้างฟังก์ชั่น wrapper ที่ใช้get_termsและ (ตามเงื่อนไข) เพิ่มตัวกรองเพื่อจัดการเคียวรี SQL (เพื่อ จำกัด ตามประเภทโพสต์)

get_terms($taxonomies, $args)ฟังก์ชั่นใช้อาร์กิวเมนต์เดียวกับ $argsรับอาร์กิวเมนต์เพิ่มเติมpost_typesซึ่งรับอาร์เรย์ | string ของชนิดการโพสต์

แต่ฉันไม่สามารถรับประกันได้ว่าทุกอย่างทำงานได้ตามที่คาดไว้ (ฉันกำลังคิดที่จะนับ) มันไม่ปรากฏในการทำงานโดยใช้เพียงการเริ่มต้นสำหรับ$argsget_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

ไม่ - $args = array('parent'=>0,'orderby'=>'name','hide_empty'=>0);นี้จะต้องมีอาร์เรย์: ผมจะแก้ไขนี้เพื่อให้สตริงแบบสอบถาม ...
สตีเฟ่นแฮร์ริส

ฉันจะวาง $ args ในตัวอย่างนี้ได้$terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));ที่ไหน:
user1443216

คุณไม่สามารถทำได้ในโซลูชันนั้นใหม่เท่านั้น:wpse57444_get_terms()
Stephen Harris

@ user1443216 $argsเป็นอาร์กิวเมนต์ที่สอง ที่นั่นคุณเพิ่งใส่wpse57444_get_terms( 'flag', array( 'country', 'city' ) );
ไกเซอร์

2

@ คำตอบของ stephen-harris ด้านบนใช้ได้กับฉันเพียงบางส่วนเท่านั้น หากฉันพยายามใช้สองครั้งบนหน้าเว็บมันไม่ทำงาน นอกจากนี้แนวคิดของการฝังคำสั่ง mysql เช่นนั้นทำให้ฉันกังวล - ฉันคิดว่าวิธีปฏิบัติที่ดีกว่าในการใช้วิธีการหลักในการแก้ปัญหาเพื่อหลีกเลี่ยงความขัดแย้งกับการปรับปรุง WP ในอนาคต นี่คือทางออกของฉันตามความคิดเห็น # 7 บนตั๋ว Trac ที่เขาอ้างอิง

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');

สิ่งนี้ใช้ได้กับประเภทโพสต์เดียวและ taxonomy เพียงอย่างเดียวเพราะนั่นคือสิ่งที่ฉันต้องการ แต่มันก็ไม่ยากที่จะแก้ไขสิ่งนี้เพื่อยอมรับค่าหลายค่า

มีบางคนพูดถึงเธรด Trac ที่ว่ามันอาจจะไม่ค่อยดีนัก แต่ฉันกำลังทำงานในระดับที่ค่อนข้างเล็กและไม่มีปัญหาเรื่องความเร็ว


วิธีการแก้ปัญหานี้มีลักษณะ "native" ถึง mee - anyways -> คุณควรโทรหา "wp_reset_postdata ()" ทันทีหลังจาก "endward" ของลูป: wordpress.stackexchange.com/questions/144343/ …
Thomas Fellinger

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

[แก้ไข] นี่คือความคิดเห็นเกี่ยวกับคำตอบที่ยอดเยี่ยมโดย Stephen Harris

มันไม่ได้กลับเงื่อนไขใด ๆ $flags = wpse57444_get_terms('flags', array('post_types' => array('country','city')));ถ้าใช้กับโพสต์หลายประเภทเช่นนี้ เพราะนี่คือ $ wpdb-> เตรียมความพร้อมจะทำความสะอาดสตริง $ post_types_str ไปในขณะที่มันควรจะเป็นp.post_type IN('country,city') p.post_type IN('country','city')ดูตั๋วนี้: 11102 ใช้วิธีแก้ไขปัญหาจากหัวข้อนี้เพื่อหลีกเลี่ยงปัญหานี้: /programming//a/10634225


1

ฉันยังพยายามใช้คำตอบของ @Stephen Harris แต่คำถามที่ฉันต้องการนั้นค่อนข้างยากที่จะเขียนเป็นแบบสอบถามเดียวและใช้ตัวกรอง

นอกจากนี้ฉันยังจำเป็นต้องใช้ฟังก์ชั่นนั้นหลายครั้งในหน้าเดียวกันและฉันแก้ไขปัญหาการประกาศwpse_filter_terms_by_cptฟังก์ชั่นนอกฟังก์ชั่น wrapper

Anyways @ Mark Pruce คำตอบในความคิดของฉันเหมาะกว่าด้วยเหตุผลเดียวกันกับที่เขาพูดถึงแม้ว่ามันจะต้องการให้คุณทำแบบสอบถามเพิ่มเติมอีกหนึ่ง (และห่วงที่เกี่ยวข้อง) เพื่อเตรียม args สำหรับwp_get_object_termsฟังก์ชั่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.