文章篩選功能以前寫過一個教程 WordPress 進階教程 (四十): 文章篩選功能,通過加多個分類法來實現。

過了這麼久,經常有人找我要定製文章篩選功能,現再放出代碼使用自定義字段實現,而且用自定義字段實現文章篩選,比用分類法應該更簡單,更強大。

以阿樹自己建立的一個網站作為例子:遊炎陵,這是為了推廣家鄉旅遊建立的。示例頁面:http://youyanling.com/destinations 。

前台效果:通過 url 傳遞參數。

後台效果:使用自定義字段。範例中使用自己的 ashuwp_framework 框架添加的自定義字段,都是複選框。

 

一、添加自定義字段

添加自定義字段的方法不再贅述,可以使用我們的框架,也可以使用自己的方法添加。

範例網站添加的兩個自定義字段的名稱分別為:destination_location 和 destination_season 。

自定義字段是複選框,所以值也是固定的,當然可能是字符串也可能是數組。

地域的值可能是 center 、 east 、 west 、 south,若多選了,保存的值是數組。

季節的值可能是 spring 、 summer 、 autumn 、 winter,若多選了,保存的值四號數組。

二、前台輸出篩選地址

篩選列表各個項的 url 有多種可能:

剛打開頁面時,篩選列表的 url,只需要一個參數。

西片->http://youyanling.com/destinations?area=west

南片->http://youyanling.com/destinations?area=south

...

春季->http://youyanling.com/destinations?season=spring

夏季->http://youyanling.com/destinations?season=summer

...

若點擊了其中一項,比如點擊了 「西片」 之後,此時篩選項目中地域的 url 不需要改變,但是季節的所有 url 都需要加上已經選中的 area=west 。如下

西片->http://youyanling.com/destinations?area=west

南片->http://youyanling.com/destinations?area=south

...

春節->http://youyanling.com/destinations?area=west&season=spring

夏季->http://youyanling.com/destinations?area=west&season=summer

...

同理,兩種篩選都點擊之後,此時每個篩選項目的 url 都需要帶兩個參數,且互相加上對方已經選中的參數。比如點擊了 「西片」,「春季」 兩項之後。

西片->http://youyanling.com/destinations?season=spring&area=west

南片->http://youyanling.com/destinations?season=spring&area=south

...

春節->http://youyanling.com/destinations?area=west&season=spring

夏季->http://youyanling.com/destinations?area=west&season=summer

...

而上面這種格式的 url 都是用 add_query_arg 函數輸出。

用法範例 (輸出我們需要的帶兩個參數的 url)

  1. <?php
  2. $base = 'http://youyanling.com/destinations';
  3. $params = array(
  4.   'area'=>'west',
  5.   'season'=>'spring',
  6. );
  7. //下面代碼將會輸出 http://youyanling.com/destinations?area=west&season=spring
  8. echo esc_url( add_query_arg( $params, $base ) );
  9. ?>

不管懂沒懂,反正前台輸出篩選列表得用如下代碼 (下面代碼是範例的真實代碼加了註釋),在需要出現篩選列表的位置加入如下代碼。

  1. <?php
  2. $base = get_post_type_archive_link('destination'); //篩選頁面的地址
  3. $area_sort = get_query_var('area'); //從 url 中獲取地域參數
  4. $season_sort = get_query_var('season'); //從 url 中獲取季節參數
  5. //注意,由於本篩選有兩個參數,季節和地域,所以要將地域參數讓如季節篩選的 url 中,季節的參數放入地域篩選的 url 中
  6. //檢測獲取到的季節參數是否正常
  7. $area_params = array(); //地域的參數數組
  8. if(in_array($season_sort,array('all','spring','summer','autumn','winter'))){
  9.   $area_params['season'] = $season_sort//若季節正常,將季節參數放入地域篩選的 url 中
  10. }
  11. //檢測獲取到的地域參數是否正常
  12. $season_params = array(); //季節的參數數組
  13. if(in_array($area_sort,array('all','center','east','west','south'))){
  14.   $season_params['area'] = $area_sort//若地域正常,將地域參數放入季節篩選的 url 中
  15. }
  16. $selected = 'class="selected"';
  17. ?>
  18. <div class="group clearfix">
  19.   <div class="group_title"> 位置:</div>
  20.   <div class="list clearfix">
  21.     <?php
  22.     //將地域數組的地域設置為 all
  23.     $area_params['area'] = 'all';
  24.     ?>
  25.     <a <?php if($area_sort=='all') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $area_params, $base ) ); ?>"> 全境</a>
  26.     <?php
  27.     //將地域數組的地域設置為 center
  28.     $area_params['area'] = 'center';
  29.     ?>
  30.     <a <?php if($area_sort=='center') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $area_params, $base ) ); ?>"> 城區周邊</a>
  31.     <?php $area_params['area'] = 'west'; ?>
  32.     <a <?php if($area_sort=='west') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $area_params, $base ) ); ?>"> 西片</a>
  33.     <?php $area_params['area'] = 'south'; ?>
  34.     <a <?php if($area_sort=='south') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $area_params, $base ) ); ?>"> 南片</a>
  35.     <?php $area_params['area'] = 'east'; ?>
  36.     <a <?php if($area_sort=='east') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $area_params, $base) ); ?>"> 東片</a>
  37.   </div>
  38. </div>
  39. <div class="group clearfix">
  40.   <div class="group_title"> 季節:</div>
  41.   <div class="list clearfix">
  42.     <?php $season_params['season'] = 'all';?>
  43.     <a <?php if($season_sort=='all') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $season_params, $base ) ); ?>"> 全部</a>
  44.     <?php $season_params['season'] = 'spring';?>
  45.     <a <?php if($season_sort=='spring') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $season_params, $base ) ); ?>"> 春季</a>
  46.     <?php $season_params['season'] = 'summer';?>
  47.     <a <?php if($season_sort=='summer') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $season_params, $base ) ); ?>"> 夏季</a>
  48.     <?php $season_params['season'] = 'autumn';?>
  49.     <a <?php if($season_sort=='autumn') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $season_params, $base ) ); ?>"> 秋季</a>
  50.     <?php $season_params['season'] = 'winter';?>
  51.     <a <?php if($season_sort=='winter') echo $selected; ?> href="<?php echo esc_url( add_query_arg( $season_params, $base ) ); ?>"> 冬季</a>
  52.   </div>
  53. </div>

三、增加可查詢變量

前台輸出地址和等下後台都要用到從 url 中獲取參數,都使用了 get_query_var 這個函數,不過這個函數獲取參數還需要將你要查詢的變量加入到 「公共可查詢變量中」,這個我也不知道怎麼翻譯。

 使用如下代碼使得 area 和 season 兩個參數可用 (在 functions.php 文件中加入如下代碼) 。

  1. function ashu_query_vars($public_query_vars) {
  2.   $public_query_vars[] = 'area';
  3.   $public_query_vars[] = 'season';
  4.   return $public_query_vars;
  5. }
  6. add_action('query_vars', 'ashu_query_vars');

當然,你也可以使用 $_GET 方法來獲取變量。

四、按條件輸出文章

有了前面三步,至少在前台顯示的 url 是可以正常工作。

第四步也就是最後一步,讓前台的文章輸出我們想要的。

要點:1. 使用 pre_get_posts 鈎子來改變文章查詢的參數  2. 如何使用自定義字段查詢文章。
(在 functions.php 文件中加入如下代碼)

  1. add_action('pre_get_posts','ashuwp_custom_posts_per_page'); //使用 pre_get_posts 鈎子來改變查詢文章的參數
  2. function ashuwp_custom_posts_per_page($query){
  3.   //範例中的頁面是 destination 的歸檔頁面,所以使用 is_post_type_archive 來判斷頁面
  4.   if(is_post_type_archive('destination') && $query->is_main_query() && !is_admin()){
  5.     $relation = 0//用來計數有幾個參數
  6.     $area_sort = get_query_var('area'); //獲取地域參數
  7.     $season_sort = get_query_var('season'); //獲取季節參數
  8.     $meta_query = array(
  9.       'relation' => 'OR',
  10.     );
  11.     //判斷季節是否合法,此處就不需要 all 了,因為 all 就是所有
  12.     if(in_array($season_sort,array('spring','summer','autumn','winter'))){
  13.       $meta_query[] = array(
  14.             'key'=>'destination_season', //自定義字段的名稱
  15.         'value'=> $season_sort,
  16.         'compare'=>'LIKE', //因為自定義字段值可能保存為數組,所以按字段查詢文章時使用 LIKE
  17.           );
  18.       $relation++;
  19.     }
  20.     //判斷地域是否合法
  21.     if(in_array($area_sort,array('center','east','west','south','center'))){
  22.       $meta_query[] = array(
  23.             'key'=>'destination_location',
  24.         'value'=> $area_sort,
  25.         'compare'=>'LIKE',
  26.           );
  27.       $relation++;
  28.     }
  29.     //如果有兩個參數,relation 要設置為 AND,即兩個條件都要滿足
  30.     if($relation){
  31.       if($relation==2){
  32.         $meta_query['relation'] = 'AND';
  33.       }
  34.       $query->set('meta_query',$meta_query);
  35.     }
  36.   }
  37. }

END 。