get_terms theo loại bài tùy chỉnh


19

Tôi có hai loại bài tùy chỉnh 'quốc gia' và 'thành phố' và phân loại chung 'cờ'.

Nếu tôi sử dụng:

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

Tôi nhận được một danh sách tất cả các điều khoản trong phân loại, nhưng tôi muốn giới hạn danh sách ở loại bài 'quốc gia'.

Tôi làm nó như thế nào?


Sử dụng giải pháp mới

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

Tôi không thể lặp lại $ childTerm-> name. Tại sao?


Bạn có thể rõ ràng hơn một chút?
TheDeadMedic

Câu trả lời:


16

Tôi sợ điều này không thể thực sự (chưa?). Xem trac này: http://core.trac.wordpress.org/ticket/18106

Tương tự trên trang quản trị phân loại, số lượng bài đăng phản ánh tất cả các loại bài đăng. ( Tôi khá chắc chắn rằng cũng có một vé trac cho điều đó ) http://core.trac.wordpress.org/ticket/14084

Xem thêm, bài này liên quan .


Giải pháp mới

Sau khi viết một đoạn dưới đây, tôi đã phát hành một cách tốt hơn nhiều (theo nghĩa là bạn có thể làm được nhiều hơn) là sử dụng các bộ lọc được cung cấp trong get_terms()cuộc gọi. Bạn có thể tạo một hàm bao bọc sử dụng get_termsvà (có điều kiện) thêm bộ lọc để thao tác truy vấn SQL (để hạn chế theo loại bài đăng).

Hàm lấy các đối số tương tự như get_terms($taxonomies, $args). $argslấy đối số bổ sung trong post_typesđó lấy một mảng | chuỗi các kiểu bài.

Nhưng tôi không thể đảm bảo rằng mọi thứ đều hoạt động 'như mong đợi' (tôi đang nghĩ đến việc đếm số). Nó dường như hoạt động bằng cách sử dụng chỉ mặc định $argscho 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);           
}

Sử dụng

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

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

Công việc ban đầu

Lấy cảm hứng từ vé trac ở trên, (đã thử nghiệm và nó hoạt động với tôi)

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

Sử dụng

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

hoặc là

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

Nó hoạt động, nhưng tôi có thể làm gì với $ args của mình? Ý tôi là ... cha mẹ = 0 & orderby = tên & hide_empty = 0
user1443216

không - đây phải là một mảng : $args = array('parent'=>0,'orderby'=>'name','hide_empty'=>0);. Tôi sẽ chỉnh sửa điều này để cho phép các chuỗi truy vấn ...
Stephen Harris

Tôi có thể đặt $ args của mình ở đâu trong ví dụ này : $terms = wpse57444_filter_terms_by_cpt('flag',array('country','city'));?
dùng1443216

Bạn không thể trong đó, chỉ trong giải pháp mới:wpse57444_get_terms()
Stephen Harris

@ user1443216 $argslà đối số thứ hai. Ở đó bạn chỉ cần đặtwpse57444_get_terms( 'flag', array( 'country', 'city' ) );
kaiser

2

Câu trả lời của @ stephen-harris ở trên chỉ có tác dụng với tôi một phần. Nếu tôi cố gắng sử dụng nó hai lần trên trang, nó không hoạt động. Ngoài ra, ý tưởng chôn các truy vấn mysql như thế làm tôi lo lắng - Tôi nghĩ rằng cách tốt hơn là sử dụng các phương pháp cốt lõi để đạt được giải pháp, để tránh xung đột với các cập nhật WP trong tương lai. Đây là giải pháp của tôi, dựa trên một số nhận xét # 7 về vé Trac mà anh ấy tham khảo

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

Sử dụng:

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

Điều này chỉ hoạt động cho một loại bài đăng và một phân loại, bởi vì đó là những gì tôi cần, nhưng sẽ không quá khó để sửa đổi điều này để chấp nhận nhiều giá trị.

Có một số đề cập trên chủ đề Trac rằng điều này có thể không có quy mô tốt, nhưng tôi đang làm việc ở quy mô khá nhỏ và không có vấn đề gì với tốc độ.


giải pháp này có vẻ "bản địa" hơn đối với mee - dù sao đi nữa -> bạn nên gọi "wp_reset_postdata ()" ngay sau "end" của vòng lặp: wordpress.stackexchange.com/questions/144343/ tựa
Thomas Fellinger

2

Hai loại bài tùy chỉnh 'quốc gia' và 'thành phố' và phân loại chung 'cờ'. Bạn muốn giới hạn danh sách ở loại bài 'quốc gia'.

Đây là một giải pháp đơn giản hơn:

$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

[sửa] Đây là một nhận xét về câu trả lời xuất sắc của Stephen Harris.

Nó không trả về bất kỳ điều khoản nào nếu được sử dụng với nhiều loại bài đăng như thế này $flags = wpse57444_get_terms('flags', array('post_types' => array('country','city')));. Điều này là do $ wpdb-> chuẩn bị vệ sinh chuỗi $ post_types_str p.post_type IN('country,city')trong khi cần p.post_type IN('country','city'). Xem vé này: 11102 . Sử dụng giải pháp từ chủ đề này để giải quyết vấn đề này: /programming//a/10634225


1

Tôi cũng đã thử sử dụng câu trả lời của @Stephen Harris, nhưng truy vấn tôi cần khá khó để viết dưới dạng một truy vấn duy nhất và sử dụng các phần của bộ lọc.

Hơn nữa, tôi cũng cần sử dụng chức năng đó nhiều lần trong cùng một trang và tôi đã giải quyết vấn đề khai báo wpse_filter_terms_by_cpthàm bên ngoài hàm bao bọc.

Dù sao, câu trả lời của @Mark Pruce theo ý kiến ​​của tôi phù hợp hơn, vì những lý do tương tự như ông đã nói, mặc dù nó cần bạn thực hiện thêm một truy vấn (và vòng lặp liên quan) để chuẩn bị các đối số cho wp_get_object_termshàm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.