0%

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

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

WordPress 隨機文章:orderby rand 寫法與效能、快取問題

地球與新聞背景

部落格經營久了,很多寫得不錯的舊文章慢慢沉到後面,沒什麼人看到。在文章最後或側邊欄放一個「隨機文章」清單,每次顯示不同的幾篇,就能讓舊文章多一些曝光的機會。

這篇教你用程式碼做隨機文章,也說明網站文章很多時要注意的效能問題。

程式碼要放在哪裡?

下面的 PHP 程式碼都加在子主題的 functions.php,或用 Code Snippets 外掛新增,不要直接改主題本身的檔案。詳細說明請看 WordPress functions.php 實用程式碼整理。

基本寫法:orderby => rand

PHP
function ahwei_random_posts( $count = 5 ) {
    $query = new WP_Query( array(
        'post_type'           => 'post',
        'post_status'         => 'publish',
        'posts_per_page'      => $count,
        'orderby'             => 'rand',
        'post__not_in'        => is_singular() ? array( get_queried_object_id() ) : array(),
        'has_password'        => false,
        'ignore_sticky_posts' => true,
        'no_found_rows'       => true,
    ) );

    if ( ! $query->have_posts() ) {
        return '';
    }

    $html = '<ul class="random-posts">';
    while ( $query->have_posts() ) {
        $query->the_post();
        $html .= sprintf(
            '<li><a href="%s">%s</a></li>',
            esc_url( get_permalink() ),
            esc_html( get_the_title() )
        );
    }
    wp_reset_postdata();

    return $html . '</ul>';
}

// 短代碼:[random_posts count="5"]
add_shortcode( 'random_posts', function ( $atts ) {
    $atts  = shortcode_atts( array( 'count' => 5 ), $atts );
    $count = max( 1, min( 20, absint( $atts['count'] ) ) );
    return ahwei_random_posts( $count );
} );

幾個參數的用意:

  • 'orderby' => 'rand':隨機排序。
  • post__not_in:在文章頁時,排除正在看的這一篇。
  • 'has_password' => false:不顯示有密碼保護的文章。
  • no_found_rows:不需要分頁,省掉計算總篇數的查詢。

放到網站上

  • 文章內或小工具:加一個「短代碼」區塊,填入 [random_posts count="5"]。
  • 區塊主題:到「外觀 → 編輯器 → 範本 → 單篇文章」,在文章內容下方加入「短代碼」區塊。
  • 傳統主題:在子主題的 single.php 想顯示的位置加上 <?php echo ahwei_random_posts( 5 ); ?>。

清單的樣式可以用 CSS 針對 .random-posts 調整。

舊版程式碼的問題

這篇文章舊版的程式碼直接寫 SQL 查資料庫,還用資料表裡的 guid 欄位當作文章網址。guid 只是文章的識別碼,不一定等於真正的網址(例如換過網域、改過固定網址之後就會不同),請改用上面 WP_Query 加 get_permalink() 的寫法。

文章很多時:ORDER BY RAND() 會拖慢網站

'orderby' => 'rand' 在資料庫裡是 ORDER BY RAND()。它的做法是:先幫每一篇符合條件的文章產生一個隨機數,全部排序之後,才取出前幾篇。

  • 文章不多的網站,幾乎感覺不出差別。
  • 文章數量很多、流量又大的網站,每一次瀏覽都要把所有文章排一次序,資料庫的負擔會很明顯,頁面也會變慢。

比較省資源的寫法:先取候選清單,再用 PHP 隨機挑

換個方式:先抓最近 200 篇文章的 ID 當候選清單,暫存起來;每次要顯示時,在 PHP 裡把清單打亂,取前幾篇就好。資料庫不用每次都做隨機排序。

把前面的 ahwei_random_posts() 換成下面這個版本(短代碼那一段不用改)。注意是「換掉」,同一個函式名稱出現兩次,網站會出錯:

PHP
/**
 * 取得隨機文章 ID:候選清單暫存 12 小時,在 PHP 裡隨機挑選
 */
function ahwei_random_post_ids( $count = 5 ) {
    $pool = get_transient( 'ahwei_random_pool' );

    if ( false === $pool ) {
        $pool = get_posts( array(
            'post_type'      => 'post',
            'posts_per_page' => 200,
            'fields'         => 'ids',
            'has_password'   => false,
            'no_found_rows'  => true,
        ) );
        set_transient( 'ahwei_random_pool', $pool, 12 * HOUR_IN_SECONDS );
    }

    // 在文章頁時排除目前這篇
    $current = is_singular() ? get_queried_object_id() : 0;
    $pool    = array_diff( $pool, array( $current ) );
    shuffle( $pool );

    return array_slice( $pool, 0, $count );
}

// 發佈或更新文章時,清掉候選清單,下次重新抓
add_action( 'save_post_post', function () {
    delete_transient( 'ahwei_random_pool' );
} );

function ahwei_random_posts( $count = 5 ) {
    $ids = ahwei_random_post_ids( $count );
    if ( ! $ids ) {
        return '';
    }

    $query = new WP_Query( array(
        'post__in'            => $ids,
        'orderby'             => 'post__in',
        'posts_per_page'      => count( $ids ),
        'ignore_sticky_posts' => true,
        'no_found_rows'       => true,
    ) );

    $html = '<ul class="random-posts">';
    while ( $query->have_posts() ) {
        $query->the_post();
        $html .= sprintf(
            '<li><a href="%s">%s</a></li>',
            esc_url( get_permalink() ),
            esc_html( get_the_title() )
        );
    }
    wp_reset_postdata();

    return $html . '</ul>';
}
  • 候選的 200 篇可以依網站調整。想讓更早的文章也有機會出現,就把數字調大;因為只抓 ID、又有暫存,調到上千篇負擔也不大。
  • 候選清單 12 小時才重新抓一次,發佈或更新文章時也會自動清掉重抓。
  • orderby => post__in 讓顯示順序跟隨機挑出來的順序一樣。

網站有頁面快取時,隨機文章不會變?

裝了 WP Rocket、LiteSpeed Cache 這類快取外掛,整個頁面會被存成靜態檔案送給訪客。隨機清單也跟著被存起來,在快取更新之前,每個人看到的都是同一組。

對大多數網站來說,這其實可以接受:等於每次快取更新時換一批文章,網站速度也不受影響。

如果一定要每位訪客看到不同的組合,可以改成頁面載入後,由瀏覽器用 JavaScript 向 WordPress 的 REST API 取得最近幾十篇文章,再在瀏覽器裡隨機挑幾篇顯示。這樣頁面照樣可以快取,隨機的部分交給瀏覽器處理。

隨機文章、相關文章、熱門文章怎麼選?

三種可以搭配使用,例如文章最後放相關文章、側邊欄放熱門文章。

延伸閱讀

讓讀者一篇接一篇看下去,靠的是好內容,也靠網站的動線設計。正威網路行銷是基隆在地、擁有 25 年網站設計經驗的工作室,提供基隆網頁設計與網站維護託管等服務,歡迎來聊聊。

分享這篇文章

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

發表留言

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

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