Wordpress查询自定义字段缺少帖子的顺序

nim*_*imi 3 mysql wordpress custom-fields

这是我目前的查询:

query_posts(array_merge(array('tag' => $pagetag,'meta_key'=>priority,'orderby' =>meta_value, 'order' =>'ASC','paged' => get_query_var('paged'))));
Run Code Online (Sandbox Code Playgroud)

我的问题是查询只显示了我的'meta_key'值的帖子,这意味着'priority'不是NULL.如何改进此查询以使其仍然可以通过我的meta_key排序,但是还会显示所有非NULL的帖子?

提前致谢!

Hob*_*obo 5

问题是,只要你在条件中提到,WordPress就会INNER JOINwp_postmeta表格中添加一个表格meta_key.解决这个问题的一种方法是在order by子句上添加一个过滤器,如下所示:

function so_orderby_priority($original_orderby_statement) {
    global $wpdb;

    return "(SELECT $wpdb->postmeta.meta_value
               FROM $wpdb->postmeta
              WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id
                AND $wpdb->postmeta.meta_key = 'priority') ASC";
}

add_filter('posts_orderby', 'so_orderby_priority');

query_posts(
    array(
        'tag' => $pagetag,
        'paged' => get_query_var('paged')
    )
);

remove_filter('posts_orderby', 'so_orderby_priority');
Run Code Online (Sandbox Code Playgroud)

注意MySQL首先对NULL进行排序 - 如果你希望它们最后排序,请尝试这样的事情(假设你的所有优先级按字母顺序排在ZZZZZ之前):

function so_orderby_priority($original_orderby_statement) {
    global $wpdb;

    return "IFNULL(
               (SELECT $wpdb->postmeta.meta_value
                  FROM $wpdb->postmeta
                 WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id
                   AND $wpdb->postmeta.meta_key = 'priority'),
                'ZZZZZ') ASC";
}
Run Code Online (Sandbox Code Playgroud)

编辑

这里有一些解释,假设您至少了解SQL.

您的原始query_posts结果导致对数据库运行以下查询:

SELECT wp_posts.*
FROM   wp_posts
       INNER JOIN wp_term_relationships ON ( wp_posts.id = wp_term_relationships.object_id )
       INNER JOIN wp_postmeta ON ( wp_posts.id = wp_postmeta.post_id )
WHERE  1 = 1
       AND ( wp_term_relationships.term_taxonomy_id IN ( 3 ) )
       AND wp_posts.post_type = 'post'
       AND ( wp_posts.post_status = 'publish'
              OR wp_posts.post_status = 'private' )
       AND ( wp_postmeta.meta_key = 'priority' )
GROUP  BY wp_posts.id
ORDER  BY wp_postmeta.meta_value ASC
LIMIT  0, 10; 
Run Code Online (Sandbox Code Playgroud)

INNER JOIN wp_postmeta就是删除任何没有优先结果的帖子的结果.

meta_*从您的删除相关条件query_posts:

query_posts(
    array(
        'tag' => $pagetag,
        'paged' => get_query_var('paged')
    )
);
Run Code Online (Sandbox Code Playgroud)

解决了这个问题,但排序顺序仍然是错误的.新的SQL是

SELECT wp_posts.*
FROM   wp_posts
       INNER JOIN wp_term_relationships ON ( wp_posts.id = wp_term_relationships.object_id )
WHERE  1 = 1
       AND ( wp_term_relationships.term_taxonomy_id IN ( 3 ) )
       AND wp_posts.post_type = 'post'
       AND ( wp_posts.post_status = 'publish'
              OR wp_posts.post_status = 'private' )
GROUP  BY wp_posts.id
ORDER  BY wp_posts.post_date DESC
LIMIT  0, 10; 
Run Code Online (Sandbox Code Playgroud)

posts_orderby过滤器允许我们改变ORDER BY条款:wp_posts.post_date DESC被通过过滤器返回什么取代.最终的SQL成为:

SELECT wp_posts.*
FROM   wp_posts
       INNER JOIN wp_term_relationships ON ( wp_posts.id = wp_term_relationships.object_id )
WHERE  1 = 1
       AND ( wp_term_relationships.term_taxonomy_id IN ( 3 ) )
       AND wp_posts.post_type = 'post'
       AND ( wp_posts.post_status = 'publish'
              OR wp_posts.post_status = 'private' )
GROUP  BY wp_posts.id
ORDER  BY (SELECT wp_postmeta.meta_value
           FROM   wp_postmeta
           WHERE  wp_posts.id = wp_postmeta.post_id
                  AND wp_postmeta.meta_key = 'priority') ASC
LIMIT  0, 10 
Run Code Online (Sandbox Code Playgroud)

这就是你所追求的.