WP_query: meta_key с пользовательским правилом для определенного значения

5 мая 2013 г., 20:59:11
Просмотры: 22.6K
Голосов: 2

Я столкнулся с трудностями в коде WP_Query. Вот он:

$args = array(
      'post_type' => 'post',
      'meta_query'=> array(
          'key' => 'karma',
          'compare' => '>=',
          'value' => 0,
          'type' => 'numeric'),
        'posts_per_page' => 9,
        'meta_key' => 'karma',
        'orderby' => 'meta_value_num', 
        'order' => 'DESC',
        'post__not_in' => $dont_show_me
    );

Что я хочу сделать:

Показать все записи с karma >= 0 (это работает нормально с этим кодом). НО если есть записи с karma = 100, показать только 3 из них + остальные записи.

Примеры: 9 записей с karma = 150, 133, 100, 100, 100, 100, 100, 33, 11.

Я хочу показать: 150, 133, 100, 100, 100, 33, 11. (Разрешено только 3 записи с karma = 100).

Есть ли у вас идеи, как этого достичь? Может быть, использовать add_filter('posts_where');?

ОБНОВЛЕНИЕ: Хорошо, я заставил это работать, основываясь на ответе @s_ha_dum. Это немного сложно, но результат работает ;)

$args = array(
       // Проверяем последние 9 записей с karma = 100
       'post_type' => 'post',
       'meta_query'=> array(
          array(
              'key' => 'karma',
              'compare' => '=', 
              'value' => 100,
              'type' => 'numeric'
           )
        ),
       'posts_per_page' => 9,
       'meta_key' => 'karma',
       'orderby' => 'meta_value_num', 
       'order' => 'DESC',
       'post__not_in' => $dont_show_me
    );
    $karma_qry = new WP_Query($args);

    if (!empty($karma_qry->posts)) {
        $i = 0;
        foreach ($karma_qry->posts as $p) {
            $i++;
            // Проверяем больше ли 3 записей с karma = 100
            // Добавляем их в массив $dont_show_me
            if($i > 3){
                $dont_show_me[] = $p->ID;
            }
        }
    }

    // Настраиваем финальный запрос, который исключает дополнительные записи с karma = 100
    $args['meta_query'][0]['compare'] = '>=';
    $args['meta_query'][0]['value'] = 0;
    $args['post__not_in'] = $dont_show_me;

    $wp_query = new WP_Query($args);
0
Все ответы на вопрос 1
4

meta_query - это массив массивов. Посмотрите примеры в Кодексе.

 $args = array(
   'post_type' => 'my_custom_post_type',
   'meta_key' => 'age',
   'orderby' => 'meta_value_num',
   'order' => 'ASC',
   'meta_query' => array(
       array(
           'key' => 'age',
           'value' => array(3, 4),
           'compare' => 'IN',
       )
   )
 );
 $query = new WP_Query($args);

У вас просто массив. Это может вызвать проблемы. Вот что вам нужно сделать:

$args = array(
   'post_type' => 'post',
   'meta_query'=> array(
      array(
          'key' => 'karma',
          'compare' => '>=', // ограничение по "значению karma = 100"
          'value' => 0, // ограничение по "значению karma = 100"
          'type' => 'numeric'
       )
    ),
   'posts_per_page' => 9,
   'meta_key' => 'karma',
   'orderby' => 'meta_value_num', 
   'order' => 'DESC',
   'post__not_in' => $dont_show_me
);

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

Показать все записи с karma >= 0 (это работает нормально с данным кодом). НО если есть записи с karma = 100, показать только 3 из них + остальные записи.

... с помощью одного WP_Query. Похоже, вы хотите получить ровно 3 записи с karma больше 100, а остальное заполнить любыми другими записями. Это было бы сложно реализовать на чистом SQL. Думаю, это возможно в SQL, но мне пришлось бы очень долго думать, чтобы в этом убедиться, не говоря уже о реализации.

Я бы предложил два запроса — один для получения записей "больше 100", а второй — для всех остальных.

$dont_show_me = array(1);
$args = array(
   'post_type' => 'post',
   'meta_query'=> array(
      array(
          'key' => 'karma',
          'compare' => '>=', 
          'value' => 100,
          'type' => 'numeric'
       )
    ),
   'posts_per_page' => 3,
   'meta_key' => 'karma',
   'orderby' => 'meta_value_num', 
   'order' => 'DESC',
   'post__not_in' => $dont_show_me
);
$karma_qry = new WP_Query($args);

if (!empty($karma_qry->posts)) {
  $args['posts_per_page'] = 9 - $karma_qry->found_posts;
  $args['meta_query'][0]['value'] = 0;
  foreach ($karma_qry->posts as $p) {
      // предполагаем, что $dont_show_me - это массив
      $dont_show_me[] = $p->ID;
  }
  $args['post__not_in'] = $dont_show_me;
} else {
  $args['posts_per_page'] = 9;
  $args['meta_query'][0]['value'] = 0;
}

$the_rest_qry = new WP_Query($args);

Я не могу протестировать это, так как у меня нет ваших данных karma на сервере, но я почти уверен, что это верно. По крайней мере, это должно помочь вам продвинуться в решении задачи.

5 мая 2013 г. 21:40:22
Комментарии

Спасибо за ваш ответ. Но ваш код показывает только посты с кармой = 100. Я хочу показывать все посты с кармой >= 0, НО если у поста карма = 100, то показывать только 3 из них. (Я отредактирую свой вопрос).

hawkidoki hawkidoki
5 мая 2013 г. 22:12:37

@hawkidoki : смотрите правки.

s_ha_dum s_ha_dum
6 мая 2013 г. 00:12:49

Действительно интересное решение! Для других людей: есть ошибка ближе к концу вашего кода $args['post__no_in'] (должно быть post__not_in).

Ваше решение, кажется, работает, мне нужно немного его доработать, но идея отличная :) Большое спасибо!

hawkidoki hawkidoki
6 мая 2013 г. 01:23:41

@hawkidoki : Я исправлю эту ошибку. Спасибо. И вопросы, и ответы здесь редактируются сообществом, как в вики. Вы можете исправлять подобные ошибки самостоятельно.

s_ha_dum s_ha_dum
6 мая 2013 г. 02:39:11