用自定义字段做文章多重筛选

文章筛选功能以前写过一个教程wordpress进阶教程(四十):文章筛选功能,通过加多个分类法来实现。

过了这么久,经常有人找我要定制文章筛选功能,现再放出代码使用自定义字段实现,而且用自定义字段实现文章筛选,比用分类法应该更简单,更强大。

2017-06-26更新

如果你不会代码,照着教程也会出错,或者你懒得写,你可以试试我们的付费拓展

敬告:代码很长,手打难免出错,若是出现错误,请谅解。

前言

1. 本范例实现的筛选页面可用于分类页面、单页面。

2. 本筛选范例是通过文章的自定义字段来实现的。

3. 筛选页面的url,以分类页面为例:http://www.ashuwp.com/category1/?genre=love&year=y2017&area=china。通过在url后面加参数实现。

一、配置筛选数据。

用于筛选的数据要先确定好,所以阿树先把要筛选的数据写入一个二维数组中,同时由于这个数组在前台后台都会使用到,所以用一个函数来返回,即执行函数ashuwp_get_sift_array()就可以获取到这个二维数组。

本范例以一个电影站的筛选为例,配置了3个筛选项(可自行增减),分别是“类型”、“年代”、“地区”。

提示:下面php代码应该添加到主题的functions.php文件。

  1. //准备一个筛选数据的数组。
  2. //需要多次用到,用一个函数来获取。
  3. function ashuwp_get_sift_array(){
  4.   $sift_array = array(
  5.     //类型
  6.     'genre'=> array(
  7.       'love'=>'爱情片',
  8.       'literary'=>'文艺片',
  9.       'action'=>'动作片',
  10.       'war'=>'战争片',
  11.       'other'=>'其他'
  12.     ),
  13.     //数组key避免用纯数字,以免筛选文章时不精确
  14.     //将key缓存a\b\c也可
  15.     'year'=> array(
  16.       'y2017'=>'2017',
  17.       'y2016'=>'2016',
  18.       'y2015'=>'2015',
  19.       'old'=>'更早',
  20.     ),
  21.     'area'=> array(
  22.       'china'=>'国产',
  23.       'usa'=>'美国',
  24.       'europe'=>'欧洲',
  25.       'other'=>'其他'
  26.     )
  27.   );
  28.   return $sift_array;
  29. }

二、添加自定义字段

在后台建立自定义字段,在添加文章时选择对应的数据。

方法一:使用Ashuwp Framework框架的话,参考配置数据以及效果图如下

提示:下面代码为使用Ashuwp Framework框架的配置代码。

  1. //文章筛选面板
  2. $sift_boxinfo = array(
  3.   'title' => '筛选信息',
  4.   'id'=>'sift_box',
  5.   'page'=>array('post'), //文章类型
  6.   'context'=>'normal',
  7.   'priority'=>'high',
  8.   'callback'=>''
  9. );
  10. $sift_array = ashuwp_get_sift_array(); //获取筛选数组
  11. $sift_meta[] = array(
  12.   'name' => '类型',
  13.   'id'   => 'genre', //id
  14.   'desc' => '',
  15.   'std'  => '',
  16.   'subtype'=> $sift_array['genre'], //地区选项
  17.   'type' => 'checkbox',
  18. );
  19. $sift_meta[] = array(
  20.   'name' => '年代',
  21.   'id'   => 'year', //id
  22.   'desc' => '',
  23.   'std'  => '',
  24.   'subtype'=> $sift_array['year'], //地区选项
  25.   'type' => 'checkbox',
  26. );
  27. $sift_meta[] = array(
  28.   'name' => '国家或地区',
  29.   'id'   => 'area', //id
  30.   'desc' => '',
  31.   'std'  => '',
  32.   'subtype'=> $sift_array['area'], //地区选项
  33.   'type' => 'checkbox',
  34. );
  35. $sift_box = new ashuwp_postmeta_feild($sift_meta$sift_boxinfo);

方法二:使用wordpress自带的自定义栏目,添加数据方法如下图

三、文章查询

通过从url中获取筛选的参数,查询对应的文章数据。

1. 添加用于查询的参数,这里指的是使我们的参数可以用get_query_var函数获取,当然如果使用$_GET变量来获取的话,可以省略这一段内容。

提示:下面php代码应该添加到主题的functions.php文件。

自己添加的query vars应尽量避免wp默认已经存在的,比如本教程中的year实际上wp默认已经存在,请实际使用时避免。那些已经存在呢?请查看文档:https://codex.wordpress.org/WordPress_Query_Vars。

  1. //筛选参数
  2. //筛选页面的url类似为 http://www.ashuwp.com/xxx?genre=love&year=2016&area=china
  3. function ashuwp_add_query_vars($public_query_vars) {
  4.   $public_query_vars[] = 'genre';
  5.   $public_query_vars[] = 'year';
  6.   $public_query_vars[] = 'area';
  7.   return $public_query_vars;
  8. }
  9. add_action('query_vars', 'ashuwp_add_query_vars');

2. 通过pre_get_posts钩子来控制文章查询

  1. //文章筛选代码
  2. //通过pre_get_posts钩子筛选
  3. add_action('pre_get_posts','ashuwp_sift_posts_per_page');
  4. function ashuwp_sift_posts_per_page($query){
  5.   //is_category()即为分类页面有效,自行更换。
  6.   //$query->is_main_query()使得仅对默认的页面主查询有效
  7.   //!is_admin()避免影响后台文章列表
  8.   if(is_category() && $query->is_main_query() && !is_admin()){
  9.     $sift_array = ashuwp_get_sift_array(); //获取筛选数组
  10.     //从筛选数组中获取筛选的有效值值
  11.     /*例如类型的值
  12.     * $genre_keys = array( 'love', 'literary', 'action', 'war', 'other');
  13.     */
  14.     $genre_keys = array_keys$sift_array['genre'] ); //类型
  15.     $year_keys = array_keys$sift_array['year'] ); //年代
  16.     $area_keys = array_keys$sift_array['area'] ); //地区
  17.     $relation = 0; //用于计数筛选项目数
  18.     //从url中获取要筛选的参数,放入数组中
  19.     $sift_vars = array();
  20.     $sift_vars['genre'] = get_query_var('genre'); //从url获取类型
  21.     $sift_vars['year'] = get_query_var('year');
  22.     $sift_vars['area'] = get_query_var('area');
  23.     $meta_query = array(
  24.       'relation' => 'OR',
  25.     );
  26.     //判断类型是否合法,即是否存在于我们的配置数组中
  27.     //将筛选参数加入带
  28.     if( in_array( $sift_vars['genre'], $genre_keys ) ){
  29.       $meta_query[] = array(
  30.         'key'=>'genre',
  31.         'value'=> $sift_vars['genre'],
  32.         'compare'=>'LIKE', //使用LIKE匹配可适应多选
  33.       );
  34.       $relation++;
  35.     }
  36.     //判断年代是否合法
  37.     if( in_array( $sift_vars['year'], $year_keys ) ){
  38.       $meta_query[] = array(
  39.         'key'=>'year',
  40.         'value'=> $sift_vars['year'],
  41.         'compare'=>'LIKE',
  42.       );
  43.       $relation++;
  44.     }
  45.     //判断地区是否合法
  46.     if( in_array( $sift_vars['area'], $area_keys ) ){
  47.       $meta_query[] = array(
  48.         'key'=>'area',
  49.         'value'=> $sift_vars['area'],
  50.         'compare'=>'LIKE',
  51.       );
  52.       $relation++;
  53.     }
  54.     if($relation){
  55.       //若大于两个筛选
  56.       if($relation>=2){
  57.         $meta_query['relation'] = 'AND'; //多项筛选同时满足
  58.       }
  59.       $query->set('meta_query',$meta_query);
  60.     }
  61.   }
  62. }

三、前台代码

 范例代码以在分类页面中为例。
提示:下面代码为部分范例代码,应该将下列代码添加到主题分类模板需要显示筛选的位置。
  1. //前台页面以在分类模板为例
  2. //在分类模板中,使用get_queried_object获取当前分类
  3. $currentterm = get_queried_object();
  4. $base_url = get_term_link($currentterm,'category'); //获取当前分类的url
  5. $sift_array = ashuwp_get_sift_array(); //获取筛选数组
  6. //拆分数组,将all加上
  7. /*范例,最终
  8. * $genre_array = array( 'all'=>'全部', 'love'=>'爱情片', 'literary'=>'文艺片', 'action'=>'动作片', 'war'=>'战争片', 'other'=>'其他' );
  9. * $genere_keys = array( 'all', 'love', 'literary', 'action', 'war', 'other');
  10. */
  11. $genre_array['all'] = '全部'; //先建立数组,让all在最前面
  12. $genre_array = array_merge$genre_array$sift_array['genre']); //用array_merge合并数组
  13. $genre_keys = array_keys( $genre_array);
  14. $year_array['all'] = '全部';
  15. $year_array = array_merge$year_array$sift_array['year']);
  16. $year_keys = array_keys( $year_array);
  17. $area_array['all'] = '全部';
  18. $area_array = array_merge$area_array$sift_array['area']);
  19. $area_keys = array_keys( $area_array);
  20. //从url中获取要筛选的参数,放入数组中,默认为all
  21. $sift_vars = array();
  22. $sift_vars['genre'] = get_query_var('genre', 'all'); //从url获取类型
  23. $sift_vars['year'] = get_query_var('year', 'all');
  24. $sift_vars['area'] = get_query_var('area', 'all');
  25. //为add_query_arg函数的参数做准备
  26. $genre_params = array();
  27. $year_params = array();
  28. $area_params = array();
  29. //判断类型是否合法,给另外N项加上
  30. if( in_array( $sift_vars['genre'], $genre_keys ) ){
  31.   $year_params['genre'] = $sift_vars['genre'];
  32.   $area_params['genre'] = $sift_vars['genre'];
  33. }
  34. //判断年代是否合法,给另外N项加上
  35. if( in_array( $sift_vars['year'], $year_keys ) ){
  36.   $genre_params['year'] = $sift_vars['year'];
  37.   $area_params['year'] = $sift_vars['year'];
  38. }
  39. //判断地区是否合法,给另外N项加上
  40. if( in_array( $sift_vars['area'], $area_keys ) ){
  41.   $genre_params['area'] = $sift_vars['area'];
  42.   $year_params['area'] = $sift_vars['area'];
  43. }
  44. $selected = 'class="selected"';
  45. //输出筛选项
  46. //html标签仅做参考
  47. ?>
  48. <div class="group clearfix">
  49.   <ul>
  50.     <li>
  51.       <span>类型:</span>
  52.       <?php
  53.       foreach$genre_array as  $key=>$name ){
  54.         $genre_params['genre'] = $key;
  55.       ?>
  56.       <a <?php if$sift_vars['genre'] == $key ) echo $selected; ?> href="<?php echo esc_url( add_query_arg( $genre_params, $base_url ) ); ?>"><?php echo $name; ?></a>
  57.       <?php
  58.       }
  59.       ?>
  60.     </li>
  61.     <li>
  62.       <span>年代:</span>
  63.       <?php
  64.       foreach$year_array as  $key=>$name ){
  65.         $year_params['year'] = $key;
  66.       ?>
  67.       <a <?php if$sift_vars['year'] == $key ) echo $selected; ?> href="<?php echo esc_url( add_query_arg( $year_params, $base_url ) ); ?>"><?php echo $name; ?></a>
  68.       <?php
  69.       }
  70.       ?>
  71.     </li>
  72.     <li>
  73.       <span>地区:</span>
  74.       <?php
  75.       foreach$area_array as  $key=>$name ){
  76.         $area_params['area'] = $key;
  77.       ?>
  78.       <a <?php if$sift_vars['area'] == $key ) echo $selected; ?> href="<?php echo esc_url( add_query_arg( $area_params, $base_url ) ); ?>"><?php echo $name; ?></a>
  79.       <?php
  80.       }
  81.       ?>
  82.     </li>
  83.   </ul>
  84. </div>

总结

end.

本篇教程之前的几篇教程是

本篇教程之后的几篇教程是

没有找到你要找的内容?你可以通过搜索你要找的内容,或者给我们留言。

已有18条评论

  1. philo
    philo : 回复

    请问主题分类模板是那个文件呢?我在index.php 和single.php上都加了,没反应,大神如果看到的话,求告知,感谢!

  2. 张先生
    张先生 : 回复

    请问出现这个错误是什么原因啊?Fatal error: Class ‘ashuwp_postmeta_field’ not found in F:\xampp\htdocs\xinfangyuan\wp-content\themes\xinfangyuan\metabox.php on line 199

    • 阿树工作室
      阿树工作室 回复张先生: 回复

      您好,第二步添加自定义字段,使用了Ashuwp Framework框架,对应的配置代码是Ashuwp Framework框架的代码,ashuwp_postmeta_feild类是框架了里面的,所以,你需要加载Ashuwp Framework框架,请查看本工作室提供的Ashuwp Framework使用方法。

  3. 痞子
    痞子 : 回复

    在最后一段代码里的第15行 $genere_keys 写错了吧,多了个e

    • 阿树工作室
      阿树工作室 回复痞子: 回复

      还真是,已更正。

  4. 野图
    野图 : 回复

    通过给文章筛选代码中的is_category()加上分类参数实现了仅对指定分类有效。

  5. 野图
    野图 : 回复

    这个字段筛选法能仅对某个分类有效吗?目前这样会作用所有分类,没该字段的文章会不显示。

  6. 野图
    野图 : 回复

    你好,如果要实现不同的一级分类调用不同的筛选条件要怎么实现呢?上面加到functions的代码多写几次吗?

    • 阿树工作室
      阿树工作室 回复野图: 回复

      你好,目前的代码不能做到不同的分类使用不同的字段,所以不能实现不同分类不同筛选条件。

  7. 野图
    野图 : 回复

    最后面一段代码结尾的
    <?php
    }
    是不是多余的?

    • 阿树工作室
      阿树工作室 回复野图: 回复

      多谢提醒,确实多打了,已删除。

  8. 刘荣焕
    刘荣焕 : 回复

    博主,我使用https://www.advancedcustomfields.com/ 这个插件制作自定义字段应该也是可以的吧

    • 阿树工作室
      阿树工作室 回复刘荣焕: 回复

      可以,,只要是自定义字段就可以

  9. 刘荣焕
    刘荣焕 : 回复

    destination是自定义分类法么,博主

  10. 夕照
    夕照 : 回复

    怎么在前台输出呢

  11. 墨城
    墨城 : 回复

    请问这个怎么循环输出内容

  12. 天天
    天天 : 回复

    博主,想问下如果这个要分页的话,是怎么弄

    • 阿树工作室
      阿树工作室 回复天天: 回复

      正常分页即可。

发表评论