WordPress的查询,以便通过自定义字段缺少帖子

WordPress的查询,以便通过自定义字段缺少帖子

问题描述:

这是我当前的查询:WordPress的查询,以便通过自定义字段缺少帖子

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

我的问题是,查询显示我只为我的“meta_key”的值意味着“优先”是不是交空值。 我该如何改进这个查询,以便它仍然可以通过我的meta_key命令,但是会显示所有不是NULL的帖子?

在此先感谢!

问题在于,只要您在条件中提及meta_key,WordPress就会将INNER JOIN添加到wp_postmeta表中。解决该问题的一个方法是添加过滤器上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就是删除任何信息而无需从结果中的优先事项。

query_posts删除meta_*相关情况:

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 

这是做什么你后。

+0

谢谢!工作很棒......代码很好......但如果你能解释一下你做了什么,我可能会很开心。林新手在PHP中,并没有真正完全得到它...有什么不同的功能查询原始查询?过滤器究竟做了什么? – nimi

+0

很高兴帮助。因为'query_posts'生成SQL以在幕后对数据库运行,所以该解决方案比MySQL更多的MySQL。该过滤器完全替换了SQL中的排序顺序,代码将按照您需要的方式对结果进行排序。我会编辑我的答案以添加更多细节。 – Hobo

+0

谢谢!伟大的答案和解释... – nimi

我需要的users.php页面上执行类似的任务我添加了一个自定义的列,并用下面的代码,我从流浪汉

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; 
} 
+0

我知道这个答案不完全符合个人问题,但我想简单地记录我的答案,因为我能够解决我的问题,使用标记的答案 –

+1

这实际上帮助我绊倒进入它在这里。 我有last_login日期作为长文本存储在用户元区域。我还为users.php表添加了3个新列。 这只是实际上对从元区域拉出的日期用户列进行排序的方法(pre_user_query)。感谢您的深思熟虑的答复。 – bshea

做到这一点,最简单的方法是插入使用save_post动作的自定义字段,所以公布的每一个岗位都会有自己的meta_key有默认值。

使用MySQL查询添加post_meta到所有帖子都没有元。而已。

如果你/有人需要对这个代码的帮助,只需回复:)

UPDATE

由于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); 
    } 
} 
+0

从一开始就添加一些代码示例(发布答案时)可能会使其更加清楚您的意思。 – Timusan

的问题:排序由自定义字段不排除不具有该定义字段设置的值帖子。

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功能)

希望这可以帮助别人!