0%

正威網路行銷工作室,專注於基隆、台北與全台客製化網頁設計,提供專業 RWD 響應式、SEO 搜尋引擎優化、品牌形象設計與網站維護託管服務。

搜尋文章
聯絡資訊
地址基隆市仁二路 220 號 5 樓
追蹤我們

WordPress 分類頁、標籤頁也能置頂文章:不用外掛的程式碼寫法

一階一階往上疊的積木

WordPress 有「置頂文章」的功能,但很多人設定之後才發現:置頂只在首頁的文章列表有效,點進分類頁或標籤頁,置頂的文章還是照日期排在原本的位置。

例如你想讓「WordPress 教學」分類的讀者,一進來就先看到一篇入門指南,就需要自己加一段程式碼。

為什麼分類頁不會置頂?

WordPress 核心只在「文章首頁」(is_home())的第一頁處理置頂文章,分類頁、標籤頁、日期彙整頁都不會。所以要自己告訴 WordPress:在分類頁和標籤頁,也把置頂文章排到最前面。

先把文章設為置頂

  • 編輯文章時,在右側的文章設定裡勾選「置頂」的選項。
  • 或到「文章 → 所有文章」,在文章上按「快速編輯」,勾選置頂。

程式碼:分類頁、標籤頁也置頂

做法分成三步:

  1. 找出「屬於目前這個分類或標籤」的置頂文章。
  2. 用 pre_get_posts 把它們從原本的文章列表排除,避免重複出現。
  3. 用 the_posts 在第一頁的最前面把它們加回去。

程式碼加在子主題的 functions.php,或用 Code Snippets 外掛新增(說明請看 WordPress functions.php 實用程式碼整理):

PHP
/**
 * 取得「屬於目前分類或標籤」的置頂文章 ID
 */
function ahwei_term_sticky_ids( $term ) {
    static $cache = array();

    $sticky = get_option( 'sticky_posts' );
    if ( ! ( $term instanceof WP_Term ) || empty( $sticky ) ) {
        return array();
    }

    if ( ! isset( $cache[ $term->term_id ] ) ) {
        $cache[ $term->term_id ] = get_posts( array(
            'post__in'            => $sticky,
            'post_type'           => 'post',
            'posts_per_page'      => -1,
            'fields'              => 'ids',
            'ignore_sticky_posts' => true,
            'no_found_rows'       => true,
            'tax_query'           => array(
                array(
                    'taxonomy' => $term->taxonomy,
                    'field'    => 'term_id',
                    'terms'    => $term->term_id,
                ),
            ),
        ) );
    }

    return $cache[ $term->term_id ];
}

/**
 * 是不是要處理的查詢:前台、主要查詢、分類頁或標籤頁、不是 RSS
 */
function ahwei_is_term_archive_query( $query ) {
    return ! is_admin()
        && $query->is_main_query()
        && ( $query->is_category() || $query->is_tag() )
        && ! $query->is_feed();
}

// 1) 從原本的列表排除置頂文章,避免重複出現
add_action( 'pre_get_posts', function ( $query ) {
    if ( ! ahwei_is_term_archive_query( $query ) ) {
        return;
    }
    $ids = ahwei_term_sticky_ids( $query->get_queried_object() );
    if ( $ids ) {
        $query->set( 'post__not_in', array_merge( (array) $query->get( 'post__not_in' ), $ids ) );
    }
} );

// 2) 在第一頁的最前面加回置頂文章
add_filter( 'the_posts', function ( $posts, $query ) {
    if ( ! ahwei_is_term_archive_query( $query ) || $query->is_paged() ) {
        return $posts;
    }
    $ids = ahwei_term_sticky_ids( $query->get_queried_object() );
    if ( ! $ids ) {
        return $posts;
    }
    $stickies = get_posts( array(
        'post__in'            => $ids,
        'orderby'             => 'post__in',
        'posts_per_page'      => count( $ids ),
        'ignore_sticky_posts' => true,
    ) );
    return array_merge( $stickies, $posts );
}, 10, 2 );

這段程式的行為:

  • 只有屬於這個分類或標籤的置頂文章會出現。子分類的文章也算在上層分類裡,跟分類頁本身的規則一樣。
  • 只在第一頁置頂,第二頁以後不會再出現,也不會跟一般文章重複。
  • 第一頁的文章數會是「置頂篇數+每頁篇數」,例如每頁 10 篇、置頂 2 篇,第一頁會有 12 篇。
  • 首頁、RSS、後台都不受影響。
  • 傳統主題,或區塊主題裡沿用範本查詢的「文章查詢迴圈」區塊,都適用。

幫置頂文章加上樣式

WordPress 只有在首頁才會幫置頂文章加上 sticky 這個 class,分類頁不會。加上這段,分類頁、標籤頁的置頂文章也會有 sticky class:

PHP
add_filter( 'post_class', function ( $classes, $class, $post_id ) {
    if ( ( is_category() || is_tag() ) && ! is_paged() && is_sticky( $post_id ) && ! in_array( 'sticky', $classes, true ) ) {
        $classes[] = 'sticky';
    }
    return $classes;
}, 10, 3 );

再用 CSS 讓它醒目一點:

CSS
.category .type-post.sticky,
.tag .type-post.sticky {
  border-left: 4px solid #e67e22;
  padding-left: 1em;
}

傳統主題也可以在列表的範本裡,於標題旁邊加上「置頂」小標籤:

PHP
<?php if ( is_sticky() ) : ?>
    <span class="sticky-badge">置頂</span>
<?php endif; ?>

舊版程式碼為什麼換掉?

這篇文章舊版的程式碼只用一個 the_posts filter,自己逐一比對分類、標籤、年份、月份、作者,程式很長、不好維護;判斷分類時也沒有把子分類算進去。新的寫法用 pre_get_posts 把排除的工作交給 WordPress 的查詢處理,程式短很多,也不會在第二頁以後重複出現。

不寫程式的做法

  • 區塊主題的「文章查詢迴圈」:如果是自己在頁面上放的文章查詢迴圈區塊(沒有沿用範本的查詢),區塊設定裡通常可以選擇置頂文章要包含、排除,或只顯示置頂文章。
  • 在分類說明放精選文章:到「文章 → 分類」編輯分類的「內容說明」,放上幾篇推薦文章的連結。主題有顯示分類說明的話,就會出現在分類頁上方。

延伸閱讀

分類頁整理得好,讀者一進來就能找到最重要的文章。正威網路行銷是 25 年經驗的基隆網頁設計工作室,也服務台北與全台客戶,提供客製化網頁設計與 SEO 搜尋引擎優化,歡迎來聊聊。

分享這篇文章

返回文章列表更多「Wordpress代碼教學」文章

發表留言

還沒有人留言,歡迎第一個分享你的想法或問題。留言經審核後才會顯示,Email 不會公開。

讓我們一起打造
您的專屬網站!