按元值或日期排序?


10

得到了一个自定义字段,startDate但仅在少数事件中存在。我想知道是否没有设置我可以post_date用来生成帖子列表的帖子?

// if meta_key _postmeta.startDate isn't set get the rest by posts.post_date

query_posts(
    array(
        array(
            'posts_per_page' => 10,
            'meta_key' => 'startDate',
            'meta_value' => date('Y-m-d'),
            'meta_compare' => '<',
            'orderby' => 'meta_value',
            'order' => 'ASC'
        ), 
        array(
            'meta_key' => 'post_date',
            'meta_value' => date('Y-m-d'),
            'meta_compare' => '<'
        )
    )
);

post_date是自定义字段吗?
Bainternet 2011年

我可能假定它是默认的wordpress发布字段,但可能是错误的?两种方法都喜欢使用默认日期...
v3nt 2011年

好吧,所以它不是一个元字段,它在posts表中
Bainternet 2011年

修复了您的查询参数,希望完全不会歪曲您所说明的内容,如有必要,请随时进行恢复。
t31os 2011年

干杯t31os-再次对其进行编辑以使其更加清晰。需要它使用startDate选择比NOW更早的内容,并且如果尚未设置startDate,请使用默认帖子的日期post_date。
v3nt 2011年

Answers:


11

如果可以用SQL解释它,则可以查询它!我们要在三个地方更改默认查询:

SELECT wp_posts.*
FROM wp_posts 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
WHERE 1=1
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish')
    AND wp_postmeta.meta_key = 'startDate'
    AND CAST(wp_postmeta.meta_value AS CHAR) < '2011-03-23'
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value DESC
LIMIT 0, 10
  • 联接应该是左联接
  • 子句
  • 命令

通过函数添加_get_meta_sql() join和where-clause 。输出经过过滤,因此我们可以将其插入:

add_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' );
function wpse12814_get_meta_sql( $meta_sql )
{
    // Move the `meta_key` comparison in the join so it can handle posts without this meta_key
    $meta_sql['join'] = " LEFT JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'startDate') ";
    $meta_sql['where'] = " AND (wp_postmeta.meta_value IS NULL OR wp_postmeta.meta_value < '" . date('Y-m-d') . "')";
    return $meta_sql;
}

order子句通过posts_orderby以下方式过滤:

add_filter( 'posts_orderby', 'wpse12814_posts_orderby' );
function wpse12814_posts_orderby( $orderby )
{
    $orderby = 'COALESCE(wp_postmeta.meta_value, wp_posts.post_date) ASC';
    return $orderby;
}

这为我们提供了以下SQL查询:

SELECT wp_posts.*
FROM wp_posts
LEFT JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'startDate')
WHERE 1=1
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish')
    AND (wp_postmeta.meta_value IS NULL OR wp_postmeta.meta_value < '2011-03-23')
GROUP BY wp_posts.ID
ORDER BY COALESCE(wp_postmeta.meta_value, wp_posts.post_date) ASC
LIMIT 0, 10

记住在执行查询后要取消过滤器的钩子,否则您也会弄乱其他查询。并且,如果可能的话,您不应该query_posts()自欺欺人,而在设置页面时修改WordPress完成的主要帖子查询。


2
非常优雅的解决方案,我不会想到像那样使用COALESCE。我建议不要采用默认的'wp_'前缀,而是使用{$ wpdb-> prefix} ...
goldenapples

@goldenapples:是的,您可以对其进行概括,但是它已经非常具体地用于此查询(它将用元部分弄乱其他查询),以至于我认为没有必要。
Jan Fabry

谢谢Jan-这真是大开眼界!仍然对wordpress有所了解,想知道在我的页面上该怎么称呼它?我该如何“摘机”呢?即// // $ theQuery ...然后<?php if(have_posts()):while(have_posts()):the_post(); ?>?
v3nt 2011年

@daniel:您可以将功能放在主题functions.php文件中。然后,在执行查询之前,先放置两add_filter()行。查询后,您编写remove_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' ); remove_filter( 'posts_orderby', 'wpse12814_posts_orderby' );以再次删除它们。
1月Fabry

啊-现在一切都有意义,而且也可以工作!非常感谢Jan。那将很有用...
v3nt 2011年

0

尝试以下方法:

$postedtime = get_post_meta($post->ID, 'startDate');

if($postedtime != null){
$orderby = $postedtime;

}else{
$orderby = 'date';
}

Thankx Alex但不确定如何将其纳入循环?
v3nt 2011年

h!当您query_posts(array('orderby'=> $ orderby))
Alex Older

0

查询发布呼叫仅发出一个查询,而不是两个。因此,不能,您不能让它进行两个单独的查询然后连接结果。

记住,您要在此处选择一些帖子集,然后显示它们。该集合被一次选中。如果要获取两组独立的帖子然后进行合并,那么您就必须使用get_posts或类似的内容来自己做。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.