如何按自定义字段对“query_posts”功能进行排序,同时通过其他自定义字段限制帖子

时间:2010-11-06 00:42:22

标签: php wordpress loops 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来说太具体了吗?

2 个答案:

答案 0 :(得分:4)

我相信这会为您提供所需的一切。这是一个名为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文件中使用它。

如果您想快速测试,我已将a self-contained version of the code发布到Gist,您可以将其下载并复制到您的网络服务器根目录test.php,根据您的用例进行修改,然后向您请求浏览器使用http://example.com/test.php等网址。

希望这有帮助。

-Mike

P.S。这个答案是very similar to an answer I just gave over at WordPress Answers,这是StackOverflow的姐妹网站,很多像我这样的WordPress爱好者每天回答问题。您可能需要see that answer too,因为它有更多解释,因为您可能希望看到WordPress Answers。希望您将来考虑在there上发布WordPress问题吗?

答案 1 :(得分:0)

由于'orderby' => 'meta_value'需要meta_key,并且您的meta_key已用于比较,我认为您无法做到这一点。 meta_key只接受单个值而不接受选项数组。这绝对是一个限制,如果您找不到解决方案,我建议您打开一个请求。

就重新运行查询的按钮而言,您只需重新加载页面并传递查询变量即可更改排序。不幸的是,您仍然必须解决问题的第一部分。

更新

您总是可以使用PHP自行对返回的数组进行排序。

此外,不确定您的时间是否可用,但您可以注册一个过滤器,可以帮助您进一步自定义查询add_filter('posts_where', ...); http://codex.wordpress.org/Function_Reference/query_posts