这是我目前的查询:
query_posts(array_merge(array('tag' => $pagetag,'meta_key'=>priority,'orderby' =>meta_value, 'order' =>'ASC','paged' => get_query_var('paged'))));
我的问题是查询只向我显示了包含我的'meta_key'值的帖子,这意味着'priority'不是NULL。 如何改进此查询以使其仍然可以通过我的meta_key排序,但是还会显示所有非NULL的帖子?
提前致谢!
答案 0 :(得分:5)
问题在于,只要在条件中提及INNER JOIN
,WordPress就会向wp_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');
注意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";
}
修改强>
这里有一些解释,它假设您至少了解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;
INNER JOIN wp_postmeta
删除了您的搜索结果中没有优先级的帖子。
从meta_*
query_posts
相关条件
query_posts(
array(
'tag' => $pagetag,
'paged' => get_query_var('paged')
)
);
解决了这个问题,但排序顺序仍然是错误的。新的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;
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
完成你所追求的目标。
答案 1 :(得分:1)
我需要在users.php页面上为我添加的自定义列执行类似的任务,并使用我从Hobo修改的以下代码
add_action('pre_user_query', 'qd_users_column_orderby');
function qd_users_column_orderby($userquery){
if('my_last_login'==$userquery->query_vars['orderby']) { //check if my cusomt meta_key is the column being sorted
global $wpdb;
$userquery->query_orderby = " ORDER BY(SELECT $wpdb->usermeta.meta_value
FROM $wpdb->usermeta
WHERE $wpdb->users.ID = $wpdb->usermeta.user_id
AND $wpdb->usermeta.meta_key = 'my_last_login') ".($userquery->query_vars["order"] == "ASC" ? "asc " : "desc ")." , wp_users.user_login ".($userquery->query_vars["order"] == "ASC" ? "asc " : "desc ");
}
}
希望这有助于需要此信息的人。
为了完成整个过程,完成我个人任务的其余必要代码如下所示。
add_filter('manage_users_columns', 'qd_add_user_login_column');
function qd_add_user_login_column($columns) {
$columns['my_last_login'] = 'Last Logged In';
return $columns;
}
add_action('manage_users_custom_column', 'qd_show_user_login_column_content', 10, 3);
function qd_show_user_login_column_content($value, $column_name, $user_id) {
$user = get_userdata( $user_id );
if ( 'my_last_login' == $column_name ){
$lastLogin = get_the_author_meta('my_last_login', $user_id);
if(!$lastLogin){
return "Never";
}else{
date_default_timezone_set(get_option('timezone_string'));
return date('m/d/y g:ia', $lastLogin);
}
}
return $value;
}
add_filter( 'manage_users_sortable_columns', 'qd_users_table_sorting' );
function qd_users_table_sorting( $columns ) {
$columns['my_last_login'] = 'my_last_login';
return $columns;
}
答案 2 :(得分:0)
问题:按自定义字段排序,但不排除没有为该自定义字段设置值的帖子。
Hobo的回答很好地解释了这一点。在这里,我将提供一个更简单的替代方案,在我的情况下最终变得更容易(请注意,如果需要分页,这将无法正常工作)。
我决定在查询完成后在PHP中进行排序。 好的部分是我可以更好地控制具有空值的帖子的结尾(我希望它们最后出现)。
$query = new WP_Query($args);
//sort by rank
function customSort($a, $b)
{
$a = get_field("sort_ranking", $a);
$b = get_field("sort_ranking", $b);
//handle nulls
$a = is_numeric($a) ? $a : 9999;
$b = is_numeric($b) ? $b : 9999;
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
}
usort($query->posts, "customSort");
这里我有一个名为sort_ranking
的数字自定义字段,我用它来对ASC进行排序。具有该值的空值的帖子被分配9999,以便它们最终结束。 (注意:我使用ACF,因此get_field
功能)
希望这有助于某人!
答案 3 :(得分:-1)
最简单的方法是使用save_post
操作插入自定义字段,因此每个发布的帖子都有自己的meta_key
默认值。
使用MySQL查询添加post_meta
到所有帖子都没有meta。多数民众赞成。
如果您/任何人需要代码帮助,请回复:)
<强>更新强>
正如Timusan所说,在更改元键名后,在functions.php文件中添加此代码:
add_action('save_post', 'sidati_post_views_metakey');
function sidati_post_views_metakey ($post_id){
/*
* $post_id = is the post ID
* 'sidati_post_views' => is your metakey name (sidati is prefix always nice to add your prefix)
* 0 => the inital value
* true => (bool) add true if you want this metakkey become unique
*/
add_post_meta($post_id, 'sidati_post_views', 0, true);
}
// THIS ACTION MUST RUN ONLY ONE TIME
add_action('init', 'sidati_allposts_must_have_this');
function sidati_allposts_must_have_this(){
/* Call the WordPress DataBase class */
global $wpdb;
/* This Query will get us all the posts and pages without "sidati_post_views" metakey. */
$ids = $wpdb->get_row("SELECT ID FROM wpdb->posts WHERE post_type IN ('post', 'page') AND post_status = 'publish' AND ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'sidati_post_views')");
/* After get all posts/pages, now you need to add the meta keys (this may take a few munites if you have many posts/pages)*/
foreach ($ids as $post_id) {
add_post_meta($post_id, 'sidati_post_views', 0, true);
}
}