Как отсортировать функцию «query_posts» по настраиваемому полю, ограничивая сообщения другим настраиваемым полем

Я запрашиваю серию сообщений в WP со следующей функцией:

<?php 
$thirtydays = date('Y/m/d', strtotime('+30 days'));
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
query_posts( array( 
    'post_type' => array('post', 'real-estate'), 
    'meta_key' => 'Time          Available', 
    'meta_compare' => '<=', 
    'meta_value' => $thirtydays, 
    'paged' => $paged )); 
?>

Эта часть работает нормально. По сути, он извлекает все мои сообщения о недвижимости, но возвращает только результаты, для которых «доступное время» составляет 30 дней или меньше.

Мне это нужно, чтобы также упорядочивать сообщения в порядке возрастания от низкого к высокому, используя данные из другого настраиваемого поля «Цена».

Всякий раз, когда я добавляю стандартный 'orderby' => 'meta_value', 'meta_key' => 'Price', он больше не показывает результаты в течение 30 дней.

Можно ли как-то совместить эти два? И можно ли добавить кнопку, которая повторно запускает запрос и сортирует по цене, спальням и т. д.? Или это слишком специфично для WP?


person nurain    schedule 06.11.2010    source источник


Ответы (2)


Я считаю, что это обеспечит вам нужно. Это класс с именем PostsOrderedByMetaQuery, который расширяет WP_Query и принимает новые аргументы 'orderby_meta_key' и 'orderby_order':

class PostsOrderedByMetaQuery extends WP_Query {
  var $posts_ordered_by_meta = true;
  var $orderby_order = 'ASC';
  var $orderby_meta_key;
  function __construct($args=array()) {
    add_filter('posts_join',array(&$this,'posts_join'),10,2);
    add_filter('posts_orderby',array(&$this,'posts_orderby'),10,2);
    $this->posts_ordered_by_meta = true;
    $this->orderby_meta_key = $args['orderby_meta_key'];
    unset($args['orderby_meta_key']);
    if (!empty($args['orderby_order'])) {
      $this->orderby_order = $args['orderby_order'];
      unset($args['orderby_order']);
    }
    parent::query($args);
  }
  function posts_join($join,$query) {
    if (isset($query->posts_ordered_by_meta)) {
      global $wpdb;
      $join .=<<<SQL
INNER JOIN {$wpdb->postmeta} postmeta_price ON postmeta_price.post_id={$wpdb->posts}.ID
       AND postmeta_price.meta_key='{$this->orderby_meta_key}'
SQL;
    }
    return $join;
  }
  function posts_orderby($orderby,$query) {
    if (isset($query->posts_ordered_by_meta)) {
      global $wpdb;
      $orderby = "postmeta_price.meta_value {$this->orderby_order}";
    }
    return $orderby;
  }
}

Вы бы назвали это так:

$thirtydays = date('Y/m/d', strtotime('+30 days'));
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$query = new PostsOrderedByMetaQuery(array(
  'post_type' => array('post', 'real-estate'),
  'meta_key' => 'Time Available',
  'meta_compare' => '<=',
  'meta_value' => $thirtydays,
  'paged' => $paged,
  'orderby_meta_key' => 'Price',
  'orderby_order'    => 'DESC',
));
foreach($query->posts as $post) {
  echo " {$post->post_title}\n";
}

Вы можете скопировать класс PostsOrderedByMetaQuery в файл functions.php вашей темы или использовать его в файле .php подключаемого модуля, который вы пишете.

Если вы хотите быстро протестировать его, я опубликовал автономную версию кода. в Gist, который вы можете загрузить и скопировать в корень вашего веб-сервера как test.php, изменить для вашего случая использования, а затем запросить из своего браузера, используя URL-адрес, например http://example.com/test.php.

Надеюсь это поможет.

-Майк

P.S. Этот ответ очень похоже на ответ, который я только что дал на WordPress Answers, дочернем сайте StackOverflow, где многие энтузиасты WordPress, такие как я, ежедневно отвечают на вопросы. Вы можете увидеть, что тоже ответьте, потому что в нем есть немного больше объяснений, и потому что вы, возможно, захотите увидеть ответы WordPress. Надеюсь, в будущем вы рассмотрите возможность публикации своих вопросов по WordPress через здесь?

person MikeSchinkel    schedule 06.11.2010
comment
Я в замешательстве, как это реализовать. Когда я вставляю код, он просто показывает блок текста с именами сообщений. Я использую query_posts и динамически подтягиваю поля для каждого сообщения (например, избранное изображение, заголовок, описание, другие настраиваемые поля и т. д.). Как я могу сделать это здесь? Я попытался заменить эхо {$post-›post_title}\n; часть, но это не совсем работает. - person nurain; 08.11.2010
comment
Неважно. У меня это работает! Единственная проблема в том, что я не могу понять, почему не отображается нумерация страниц. - person nurain; 09.11.2010
comment
@nurain. Может быть, задать еще один вопрос о нумерации страниц на wordpress.stackexchange.com? Обязательно включите код темы, который вы используете, потому что ваш вопрос здесь не содержит достаточно информации, чтобы понять ваши проблемы с нумерацией страниц. - person MikeSchinkel; 09.11.2010

Поскольку для 'orderby' => 'meta_value' требуется meta_key, а ваш meta_key уже используется для сравнения, я не думаю, что вы сможете это сделать. meta_key принимает только одно значение, а не массив опций. Это определенно ограничение, и я рекомендую вам открыть запрос, если вы не найдете решения.

Что касается кнопки для повторного запуска запроса, вы можете просто перезагрузить страницу и передать переменную запроса, чтобы изменить сортировку. К сожалению, вам все еще нужно решить первую часть вашего вопроса.

ОБНОВИТЬ

Вы всегда можете самостоятельно отсортировать возвращаемый массив с помощью PHP.

Кроме того, не уверен, что вы проверяете, когда у вас есть время, но вы можете зарегистрировать фильтр, который может помочь вам настроить запрос немного дальше add_filter('posts_where', ...); http://codex.wordpress.org/Function_Reference/query_posts

person Jason McCreary    schedule 06.11.2010