好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

WordPress实现文章按照自定义字段排序 - WordPress

WordPress实现文章按照自定义字段排序

我们一起来看看WordPress实现文章按照自定义字段排序的方法,因为碰以一个朋友博客希望增加自定义字段之后再按这个字段排序了,下面是我整理了一个方法,希望能帮助到各位同学.

用Meta Query可以实现WordPress文章按照自定义排序,假设安装了WP-PostRatings给文章打分,该插件会把文章平均分存成名叫ratings_average的自定义字段,现在就来按照这个字段排序.

简洁优雅的方法,就是Meta Query,代码放在主题的functions.php里,代码如下:

function  sort_by_ratings(  $query  ){       if  ( (  $query ->is_home() ||  $query ->is_archive() ) &&  $query ->is_main_query() ) {           $query ->set(  'meta_key' ,  'ratings_average'  );           $query ->set(  'orderby' ,  'meta_value_num' );           $query ->set(  'order' ,  'DESC'  );      }  }  add_action(  'pre_get_posts' ,  'sort_by_ratings'  ); 

却有个严重的问题,该插件只会给打过分的文章创建ratings_average字段,而Meta Query只会选择带有这个字段的文章,也就是说所有没打过分的文章都会从blog首页和存档页消失.

解决的方法呢,直接点就是给每篇文章都创建这个字段,值为0.

复杂点呢,stackoverflow上有对这个问题的讨论,按照给出的方案改进了一下,找到一个暂时的解决方法如下,思路是直接修改sql语句,代码如下:

function  sort_by_ratings(  $query  ){       if  ( (  $query ->is_home() ||  $query ->is_archive() ) &&  $query ->is_main_query() ) {          add_filter(  'posts_fields' ,  'ratings_fields'  );          add_filter(  'posts_join' ,  'ratings_join'  );          add_filter(  'posts_where' ,  'ratings_where'  );            add_filter(  'posts_groupby' ,  'ratings_group'  );          add_filter(  'posts_orderby' ,  'ratings_orderby'  );      }  }  add_action(  'pre_get_posts' ,  'sort_by_ratings'  );  function  ratings_fields( $fields ){       $order_key  =  "mt1.meta_value" ;       return   $fields  .  ",$order_key AS avg" ;  }  function  ratings_join( $join ){       global   $wpdb ;       $new_join  = "          INNER JOIN  $wpdb ->postmeta ON  $wpdb ->posts.ID =  $wpdb ->postmeta.post_id          LEFT JOIN  $wpdb ->postmeta AS mt1 ON ( $wpdb ->posts.ID = mt1.post_id AND mt1.meta_key =  'ratings_average' )      ";       return   $join  .  ' '  .  $new_join ;  }  function  ratings_where( $where ){       global   $wpdb ;       $new_where  = "          AND ( $wpdb ->postmeta.meta_key =  'ratings_average'           OR  mt1.post_id IS NULL )";       return   $where  .  ' '  .  $new_where ;  }  function  ratings_group(  $group  ){       global   $wpdb ;       return   "$wpdb->posts.ID" ;  }  //phpfensi测试数据   function  ratings_orderby(  $orderby  ){       global   $wpdb ;       return   "ISNULL(avg), avg,$wpdb->posts.post_date ASC" ;  } 

生成的sql语句如下:

SELECT  SQL_CALC_FOUND_ROWS wp_posts.*,mt1.meta_value  AS   avg   FROM  wp_posts  INNER   JOIN  wp_postmeta  ON  wp_posts.ID = wp_postmeta.post_id  LEFT   JOIN  wp_postmeta  AS  mt1  ON  (wp_posts.ID = mt1.post_id  AND  mt1.meta_key =  'ratings_average' )  WHERE  1=1  AND  wp_posts.post_type =  'post'   AND  (wp_posts.post_status =  'publish'   OR  wp_posts.post_status =  'private' )  AND  (wp_postmeta.meta_key =  'ratings_average'   OR  mt1.post_id  IS   NULL  )  GROUP   BY  wp_posts.ID  ORDER   BY   ISNULL ( avg ),  avg ,wp_posts.post_date  ASC  LIMIT 0, 10 

结果是分数按照从低分到高分排序,即使order by DESC也是升序排列,如果要让高分上前面,只能用点奇怪的方法,比如最大分数是5,把posts_fields改成这样,代码如下:

function  ratings_fields( $fields ){       // 只能升序排列,所以要降序排列时先做一次运算        $max_rating  = 5;       $order_key  =  "$max_rating - mt1.meta_value" ;       return   $fields  .  ",$order_key AS avg" ;  } 

如果还有更简单的方法,欢迎留言指教.

查看更多关于WordPress实现文章按照自定义字段排序 - WordPress的详细内容...

  阅读:67次