Одна таксономия для нескольких типов записей: как скрыть пустые для конкретного типа записи?

26 авг. 2016 г., 23:27:41
Просмотры: 3.2K
Голосов: 6

У меня есть таксономия "artist" (артист), которая используется для двух типов записей: "project" (проект) и "product" (товар).

Мне нужно отобразить список "артистов", но только если у них есть связанные "товары", и только если эти товары есть в наличии.

$artists = get_terms( array(
   'taxonomy' => 'artist',
   'hide_empty' => 1,
) );

Этот код включает артистов, у которых есть "проекты", но нет "товаров". Можно ли указать, для какого типа записей должен применяться аргумент "hide_empty"?

ОБНОВЛЕНИЕ Вот что у меня получилось на данный момент:

        /*
        Полезно, когда одна таксономия применяется к нескольким типам записей
        источник: http://wordpress.stackexchange.com/a/24074/82
    */
    function get_terms_by_post_type( $taxonomies, $post_types ) {

        global $wpdb;

        $query = $wpdb->prepare(
            "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 p.post_type IN('%s') AND tt.taxonomy IN('%s')
            GROUP BY t.term_id",
            join( "', '", $post_types ),
            join( "', '", $taxonomies )
        );

        $results = $wpdb->get_results( $query );
        return $results;
       }

$artists = get_terms_by_post_type( array('artist'), array('product'));

//*
if( !empty($artists) && !is_wp_error( $artists )  ){

    // фильтруем артистов с товарами не в наличии
    foreach($artists as $k=>$artist){
        $args = array(
            'post_type'     => 'product',
            'post_status'   => 'publish',
            'posts_per_page' => -1,
            'tax_query' => array(
                'relation' => 'AND',
                array(
                    'taxonomy' => 'artist',
                    'field' => 'id',
                    'terms' => array( $artist->term_id )
                ),
                array(
                    'key' => '_stock_status',
                    'value' => 'instock'
                )
            )
        );
        $query = new WP_Query($args);
        echo $artist->slug;
        pr($query->post_count);

        if($query->post_count<1){
            unset($artists[$k]);
        }
    }
}

Код почти работает, но не исключает товары, которых нет в наличии.

1
Комментарии

Думаю, вам понадобится пользовательская функция. Этот ответ может помочь: http://wordpress.stackexchange.com/a/14334/32698

Nate Allen Nate Allen
27 авг. 2016 г. 00:06:55
Все ответы на вопрос 2
0

Ещё одно решение той же проблемы, которое немного короче и менее сложное:

function get_terms_by_posttype($taxonomy, $postType) {
    // Получаем все термины, у которых есть записи
    $terms = get_terms($taxonomy, [
        'hide_empty' => true,
    ]);

    // Удаляем термины, у которых нет записей текущего типа поста
    $terms = array_filter($terms, function ($term) use ($postType, $taxonomy) {
        $posts = get_posts([
            'fields' => 'ids',
            'numberposts' => 1,
            'post_type' => $postType,
            'tax_query' => [[
                'taxonomy' => $taxonomy,
                'terms' => $term,
            ]],
        ]);

        return (count($posts) > 0);
    });

    // Возвращаем оставшиеся термины
    return $terms;
}
1 июл. 2021 г. 10:43:54
0

Благодаря этому ответу, я смог разобраться. Вот как можно запросить термины таксономии, связанные с товарами (woocommerce), которые есть "в наличии". В этом примере используются как tax_query (для связи товаров с таксономией), так и meta_query (для исключения товаров, отсутствующих на складе).

$artists = get_terms_by_post_type( array('artist'), array('product'));

if( !empty($artists) && !is_wp_error( $artists )  ){

    // фильтруем артистов, у которых нет товаров в наличии
    foreach($artists as $k=>$artist){
        $args = array(
            'post_type'     => 'product',
            'post_status'   => 'publish',
            'posts_per_page' => -1,
            'meta_query' =>array(
                'relation' => 'AND',
                array(
                    'key' => '_stock_status',
                    'value' => 'instock',
                    'compare' => '='
                )
                ,
                array(
                    'key' => '_stock',
                    'value' => '0',
                    'compare' => '>'
                )
                ,
                array(
                    'key' => '_stock',
                    'value' => '',
                    'compare' => '!='
                )
            ),
            'tax_query' => array(
                'relation' => 'AND',
                array(
                    'taxonomy' => 'artist',
                    'field' => 'id',
                    'terms' => array( $artist->term_id )
                ),


            )
        );

        $query = new WP_Query($args);

        if($query->post_count<1){
            unset($artists[$k]);
        }
    }
}

function get_terms_by_post_type( $taxonomies, $post_types ) {

    global $wpdb;

    $query = $wpdb->prepare(
        "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 p.post_type IN('%s') AND tt.taxonomy IN('%s')
        GROUP BY t.term_id",
        join( "', '", $post_types ),
        join( "', '", $taxonomies )
    );

    $results = $wpdb->get_results( $query );

    return $results;

}
27 авг. 2016 г. 02:49:21