15 mins read2022/07/19 HEN難

WP Query 輸出指定分類中的置頂文章及一般文章


前言

最近的一個需求是,業主希望能夠自訂文章的排序 ( 原本按照日期排序 )

希望可以手動置頂

WordPress 原本就有內建置頂的功能,即 sticky post

我原本預期這是個簡單的需求,想不到比平常花了更多時間

 

需求

一句話講完需求就是:特定分類下的混合Query

  1. 取出 “指定分類” 裡面的文章,一共取 4 篇出來,預設為時間排序,新→舊
  2. 如果有置頂文章,置頂文章優先於一般文章
  3. 如果有多篇置頂文章,則置頂文章也是時間排序,新→舊
sticky post wp query
用圖片說明需求的話是這樣

 

 

置頂文章在後台的設置方法

sticky post in block editor
置頂文章在區塊編輯器的位置

 

sticky post in classic editor
置頂文章在傳統編輯器的位置

打勾後,該篇文章就會被設定為置頂

 

核心思路

  1. 先用 WP Query 抓出置頂文章
  2. 再用 WP Query 抓出一般文章 ( 排除置頂文章 )
  3. 並使用一個計數器,來計算已經輸出多少文章了

 

WP Query 的實作方式



// 取得置頂的文章ID,是一個 array
$sticky = get_option('sticky_posts');

// 重新排序,讓日期較新的文章ID在前面
rsort($sticky);

// 我們在這裡設置一個計數器,初始值是 0
$count = 0;

// 設定你要抓的分類 id,這邊我們先假設是 45
$catid = 45;


// 第一段 WP Query 開始
$args = array(
    'post_type' => 'post',       // 選擇 post type
    'post__in' => $sticky,       // 只抓置頂文章中,符合條件的
    // ⭐下方的 'ignore_sticky_posts' 可以不用打,但打了效率比較好
    'ignore_sticky_posts' => 1,  // 字面意思是是否忽略置頂文章的規則, 1 為 true , 0 為 false,詳細說明底下會說
    'cat' => $catid              // 抓取特定分類
);
// 上面整段意思就是會從 全部的置頂文章中 , 找出"分類id=45"且"posttype=post"的文章,並且"忽略置頂文章的規則"


// 下面開始就是常規的 WP Query 語句了
$the_query = new WP_Query($args);

if ($the_query->have_posts()) :
    while ($the_query->have_posts()) : $the_query->the_post();
        // 套用版型
        get_template_part('loops/blog');

        // 這邊我們讓每篇文章套完版型後,對計數器 $count的值 +1
        $count++;
        // 如果計數器 $count的值 = 4 就停止迴圈
        if ($count == 4) break;
    endwhile;
endif;

// 如果計數器已經4篇,那下面就不用執行了
if ($count < 4) { 
    // 第二段 WP Query 開始
    $args = array( 
        'post_type' => 'post',       // 選擇 post type
        'posts_per_page' => 4,       // 只抓 4 篇,這個可以不用打,但是打了可以限制 Query 數量,效率較好
        // ⭐下方的 'ignore_sticky_posts' 這邊必須要打,否則會抓出置頂文章
        'ignore_sticky_posts' => 1,  // 字面意思是是否忽略置頂文章的規則, 1 為 true , 0 為 false,詳細說明底下會說
        'cat' => $catid              // 抓取特定分類
    );

    // 下面開始就是常規的 WP Query 語句了
    $the_query = new WP_Query($args);
    if ($the_query->have_posts()) :
        while ($the_query->have_posts()) : $the_query->the_post();
            // 套用版型
            get_template_part('loops/blog');
            // 這邊我們讓每篇文章套完版型後,對計數器 $count的值 +1
            $count++;
            // 如果計數器 $count的值 = 4 就停止迴圈
            if ($count == 4) break;

        endwhile;
    endif;
}

核心代碼到這邊其實就已經完成了

 

ignore_sticky_posts 的含意

⭐ WordPress 置頂文章規則與 🤮坑

WordPress 預設有個 “置頂文章規則”

  1. 如果你的 WP Query 結果有包含到 “置頂文章” ,則會把置頂文章擺在最前面
  2. 如果你的 WP Query 結果裡面沒有 “置頂文章” ,那麼 WordPress 會幫你把所有的置頂文章抓出來擺在最前面

 

🤮這個置頂文章的坑就是,如果你有 “指定分類” 這個置頂文章的規則會失效

不然一開始我以為把 WP Query 的參數設定為這樣子就可以得到我想要的結果



$args = array(
    'post_type' => 'post',
    'ignore_sticky_posts' => 0,
    'cat' => $featured_catid
);

 

 

ignore_sticky_posts 的用法

可能的值 代表含意
true / 1 忽略/無視上方的”置頂文章規則”
false / 0 預設為false,會使用上方的”置頂文章規則”

 

代碼解釋

我們如果回頭看上方的代碼

第一段WP Query

註解說 'ignore_sticky_posts' => 1 可以不用設置,但設置效率會比較高

是因為我們已經使用 'post__in' => $sticky 來指定抓出 “置頂文章” sticky post 了,所以不需要再跑 “置頂文章規則”

設置 'ignore_sticky_posts' => 1 可以跳過 “置頂文章規則” 提高運行效率

 

第二段WP Query

註解說 'ignore_sticky_posts' => 1 必須要設置

是因為我們原本的 WP Query 目的是要抓出一般文章 ( 非置頂文章 )

但是 “置頂文章規則”2 是,當你的 WP Query 沒抓到 “置頂文章” ,會把所有的 “置頂文章” 都抓出來顯示

很顯然這不是我們要的結果,因此要設置設置 'ignore_sticky_posts' => 1 來跳過 “置頂文章規則”

 

 

覺得不錯的話,請給我點個推薦

您的支持與鼓勵是我們前進的最大動力!