industrialthemes
  • 0
Новичок

Как упорядочить по нескольким настраиваемым полям с помощью wp_query?

  • 0

У меня есть рейтинговая система, в которой пользователь может ввести настраиваемое поле «Звезды» или «Сердца», но какое бы поле они ни выбрали, им нужно ввести значение от 1 до 5. Используя wp_query, я могу успешно отсортировать по одному из этих настраиваемые поля, но я не уверен, как сортировать по обоим. Вот код, который я использую для сортировки по одному из настраиваемых полей «Звезды»:

$args=array(
'posts_per_page' => $con_review_num,
'post_type' => 'con_product_reviews',
'paged' => $paged,
'orderby' => 'meta_value',
'order' => 'DESC',
'meta_key' => 'Stars'   
);

Вот что я хочу, чтобы эта функция делала (обратите внимание на последнюю строку):

$args=array(
'posts_per_page' => $con_review_num,
'post_type' => 'con_product_reviews',
'paged' => $paged,
'orderby' => 'meta_value',
'order' => 'DESC',
'meta_key' => 'Stars Hearts'    
);

Есть ли другой способ сделать это?

Share
  1. У меня была та же проблема, и я не мог найти способ заставить это работать только с wp_query. Вместо этого я поймал фильтр posts_clauses и засунул туда свой order_by. Это также означало выполнение нескольких объединений.

    По сути, вы устанавливаете функцию для захвата posts_clauses (или одного из более строгих фильтров запроса; но давайте пока просто воспользуемся этим), а затем внутри этого JOIN к таблице post_meta для нужных вам полей, а затем упорядочиваете их.

    Важно настроить что-то, чтобы затем удалить фильтр запроса. Вы можете сделать это в конце функции, которая его перехватывает, но у меня это отдельно в моем плагине, так что я буду придерживаться этого. Здесь отлично работает событие ‘wp’.

    add_filter('posts_clauses', 'filterMarkets')
    add_filter('wp', 'removeQueryFilter');
    
    public static function removeQueryFilter() {
      remove_filter('posts_clauses', 'filterMarkets');
    }
    
    public static function filterMarkets($clauses, $wp_query) {
    global $wpdb;
    
    $clauses['join'] .=<<<SQL
    JOIN {$wpdb->postmeta} AS title_meta ON title_meta.post_id = {$wpdb->posts}.ID AND
    title_meta.meta_key = 'fest_sortby'
    JOIN {$wpdb->postmeta} AS start_date_meta ON start_date_meta.post_id = {$wpdb->posts}.ID
    AND start_date_meta.meta_key = 'fest_market_start_date'
    SQL;
    
      $clauses['orderby'] .= " title_meta.meta_value ASC";
      $clauses['orderby'] .= " start_date_meta.meta_value ASC";
    }
    return $clauses;
    

    }

    • 0
    • Спасибо. Если бы я еще не изменил все значения своих настраиваемых полей, я бы выбрал этот подход.

      • 0
    • Я понимаю, о чем вы говорите, но в идеале я бы хотел, чтобы пользователю нужно было вводить только одно настраиваемое поле для каждого сообщения, поскольку у меня так много настраиваемых полей, и я стараюсь быть с ними максимально эффективным. Мне пришлось бы изменить несколько других областей в моем коде, если бы я разделил настраиваемое поле на два настраиваемых поля, поэтому, если возможно, я хотел бы найти способ изменить логику запроса вместо пользовательского интерфейса. Однако вы правы, этот метод сработает, если я хочу пойти по этому пути.

      • 0
  2. Как насчет создания двух настраиваемых полей:

    rating_type = 'stars' or 'hearts'
    rating_score = 1-5
    

    то вы можете заказать по одному пользовательскому полю:

    $args=array(
    'posts_per_page' => $con_review_num,
    'post_type' => 'con_product_reviews',
    'paged' => $paged,
    'orderby' => 'meta_value',
    'order' => 'DESC',
    'meta_key' => 'rating_score'   
    );
    

    и чтобы узнать, какой рейтинг показывать, просто используйте:

    $rating_type = get_post_meta($post->ID,'rating_type',true);
    if ($rating_type == "stars"){
       //show star rating
    }else{
       //show heartsrating
    }
    
    • 0
  3. Вот как я добился этого, используя только одно настраиваемое поле. Вместо того, чтобы использовать «Звезды» или «Сердца» в качестве имени настраиваемого поля и «1», «2», «3» и т. д. в качестве значения, я использовал «Рейтинг» в качестве имени и «1 звезда», «2 звездочки», «3 звезды» и т. д. (или сердечки вместо звездочек) в качестве значения. Поскольку единица измерения — от 0 до 5 как для сердечек, так и для звезд, я могу сортировать только по одному значению пользовательского поля «Рейтинг», а затем анализировать значение для отображения. Вот мой код:

    <?php 
    
    // setup the query
    $args='&posts_per_page='.$con_review_num.'&post_type=con_movie_reviews&paged='.$paged.'&order=DESC&orderby='.$feedsort.'&meta_key=Rating';
    
    $review_loop = new WP_Query($args);
    
    if ($review_loop->have_posts()) : while ($review_loop->have_posts()) : $review_loop->the_post(); $postcount++;
    
        // get the custom field value
        $rating = get_post_meta($post->ID, "Rating", $single = true);
    
        $unit = "star"; //default unit is star          
        if(strpos($rating," Hearts") || strpos($rating," hearts") || strpos($rating," Heart") || strpos($rating," heart")) {
        $unit = "heart"; //find out if we're using hearts instead of stars
        }
        // extract just the number from the rating meta key
        $rating = trim(str_replace(" star","",str_replace(" stars","",str_replace(" Star","",str_replace(" Stars","",str_replace(" heart","",str_replace(" hearts","",str_replace(" Heart","",str_replace(" Hearts","",$rating)))))))));
        if($stars) { // are we using stars or hearts?
            $rating = $stars;
            $unit = "star";
        } elseif($hearts) {
            $rating = $hearts;
            $unit = "heart";
        }   
        ?>
    
        <div class="stars tooltip" title="<?php echo $rating; ?> / 5 <?php echo $overall; ?>">
    
            <div class="<?php echo $unit; ?><?php if($rating>=1) { ?> full<?php } elseif($rating>0) { ?> half<?php } ?>">&nbsp;</div>
    
            <div class="<?php echo $unit; ?><?php if($rating>=2) { ?> full<?php } elseif($rating>1) { ?> half<?php } ?>">&nbsp;</div>
    
            <div class="<?php echo $unit; ?><?php if($rating>=3) { ?> full<?php } elseif($rating>2) { ?> half<?php } ?>">&nbsp;</div>
    
            <div class="<?php echo $unit; ?><?php if($rating>=4) { ?> full<?php } elseif($rating>3) { ?> half<?php } ?>">&nbsp;</div>
    
            <div class="<?php echo $unit; ?><?php if($rating>=5) { ?> full<?php } elseif($rating>4) { ?> half<?php } ?>">&nbsp;</div>
    
        </div>
    
        <?php 
    
    }
    endwhile;
    endif;                  
    
    ?>
    
    • 0

Оставить ответ

You must login to add an answer.