0%

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

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

WordPress 依登入狀態、會員角色顯示部分內容:不用外掛的短代碼寫法

wordpress 恢復舊版 小工具 Classic Widgets 恢復舊版編輯器 disable Gutenberg 禁用古騰堡

做會員網站、內部資料區或線上課程時,常會有這些需求:

  • 文章前半段大家都能看,後半段只給登入的會員
  • 下載連結只給特定角色(例如「經銷商」)
  • 同一個位置,訪客看到「請先登入」,會員看到正式內容

裝會員外掛當然可以,但如果只是這種簡單的需求,自己寫一個短代碼就夠了。這篇整理三種寫法,從簡單到彈性。(原本另外兩篇〈用代碼讓 WordPress 的某部分內容只有註冊/登入的人才可以看到〉與〈用代碼使 WordPress 依照會員等級顯示不同的文章內容〉的內容已經整合到這裡。)

開始之前

  • 程式碼放在子主題的 functions.php,或用 Code Snippets 外掛新增。不要直接改主題本身的檔案,主題一更新就會被覆蓋。
  • 動手前先備份網站。
  • 角色與權限的觀念,可以先看WordPress 使用者角色與權限完整指南。

寫法一:只有登入的人看得到

最常見的需求:登入的人看得到內容,沒登入的人看到一段提示和登入連結。

PHP
add_shortcode( 'members', 'ahwei_members_shortcode' );

function ahwei_members_shortcode( $atts, $content = null ) {
    if ( null === $content || is_feed() ) {
        return '';
    }

    if ( is_user_logged_in() ) {
        return do_shortcode( $content );
    }

    return sprintf(
        '<p class="members-only">這段內容僅限會員閱讀,請先<a href="%s">登入</a>。</p>',
        esc_url( wp_login_url( get_permalink() ) )
    );
}

使用方式:在文章裡加入「短代碼」區塊(直接打在段落裡也可以),把會員內容包起來:

純文字
[members]這段只有登入的會員看得到。[/members]

程式碼裡用到的函式:

  • is_user_logged_in():判斷目前的訪客有沒有登入。
  • wp_login_url( get_permalink() ):登入頁的網址,登入後會自動回到這篇文章。
  • is_feed():RSS 裡一律不輸出,避免會員內容被 RSS 閱讀器抓走。

舊版的寫法在沒登入時什麼都不顯示,訪客根本不知道這裡有內容。加上提示和登入連結,會員才知道要做什麼。如果你希望完全不顯示,把最後的 return sprintf( ... ); 整段換成 return ''; 就好。

會員內容有好幾個區塊怎麼辦?

會員內容裡有圖片、清單等好幾個區塊時,可以把 [members] 放在一個短代碼區塊、[/members] 放在另一個短代碼區塊,中間夾著一般的區塊。WordPress 是先把整篇文章組好才處理短代碼,所以中間的內容會被一起包住。

寫法二:依角色、權限、帳號決定誰看得到

需要更細的條件時,用下面這個比較完整的 [eyesonly] 短代碼。舊版文章用的也是這個名稱與參數,如果你的網站以前用過,換上新的程式碼之後,舊文章裡的短代碼可以照常使用。

PHP
add_shortcode( 'eyesonly', 'ahwei_eyesonly_shortcode' );

function ahwei_eyesonly_shortcode( $atts, $content = null ) {
    $atts = shortcode_atts(
        array(
            'logged'   => '',
            'level'    => '',
            'username' => '',
            'hide'     => '',
        ),
        $atts,
        'eyesonly'
    );

    if ( null === $content || is_feed() ) {
        return '';
    }

    $user    = wp_get_current_user();
    $matched = false;

    // 條件一:登入狀態
    if ( 'in' === $atts['logged'] && is_user_logged_in() ) {
        $matched = true;
    }
    if ( 'out' === $atts['logged'] && ! is_user_logged_in() ) {
        $matched = true;
    }

    // 條件二:角色或權限(可填多個,用逗號或空格分開)
    $levels = preg_split( '/[\s,]+/', $atts['level'], -1, PREG_SPLIT_NO_EMPTY );
    foreach ( $levels as $level ) {
        if ( in_array( $level, (array) $user->roles, true ) || current_user_can( $level ) ) {
            $matched = true;
        }
    }

    // 條件三:指定帳號(可填多個)
    $names = preg_split( '/[\s,]+/', $atts['username'], -1, PREG_SPLIT_NO_EMPTY );
    if ( $user->exists() && in_array( $user->user_login, $names, true ) ) {
        $matched = true;
    }

    // hide="yes" 時規則反過來:符合條件的人看不到
    $hide = in_array( strtolower( $atts['hide'] ), array( 'yes', 'true', '1' ), true );
    $show = $hide ? ! $matched : $matched;

    return $show ? do_shortcode( $content ) : '';
}

四個參數:

  • logged:填 in 代表已登入的人,填 out 代表沒登入的訪客。
  • level:角色代稱或權限名稱,可以填多個,用逗號或空格分開,例如 administrator, editor,或自訂角色 c_business。
  • username:指定帳號(登入用的帳號名稱),可以填多個。
  • hide:填 yes 時規則反過來,符合條件的人看不到,其他人看得到。

logged、level、username 至少要填一個,可以混著用,符合其中任何一個條件就算符合。

舊版文章在網站搬家後,程式碼裡的分隔規則少了反斜線,變成 /[s,]+/。照著複製的話會變成用字母 s 來切割,名稱裡有 s 的角色(例如 subscriber)就會判斷錯誤。上面的程式碼是正確的 /[\s,]+/。

使用範例

只有管理員、自訂角色 c_business,以及有審核留言權限的人看得到:

純文字
[eyesonly level="administrator, c_business, moderate_comments"]內容[/eyesonly]

沒登入的訪客、訂閱者都看不到,其他登入的人看得到:

純文字
[eyesonly hide="yes" logged="out" level="subscriber"]內容[/eyesonly]

管理員,以及帳號 joebob、billyjean 看得到(不一定要是管理員):

純文字
[eyesonly username="joebob, billyjean" level="administrator"]內容[/eyesonly]

同一個位置,登入和沒登入的人看到不同內容:

純文字
[eyesonly logged="in"]歡迎回來,這是會員專屬內容。[/eyesonly]
[eyesonly logged="out"]登入會員即可閱讀完整內容。[/eyesonly]

寫法三:在主題範本裡依角色顯示不同內容

如果不是單篇文章,而是網站的某個固定位置(例如側邊欄、頁尾、文章範本)要依會員身分顯示不同內容,可以直接寫在子主題的範本檔案裡:

PHP
<?php if ( current_user_can( 'manage_options' ) ) : ?>
    <p>管理員看到的內容</p>
<?php elseif ( current_user_can( 'edit_others_posts' ) ) : ?>
    <p>編輯看到的內容</p>
<?php elseif ( current_user_can( 'publish_posts' ) ) : ?>
    <p>作者看到的內容</p>
<?php elseif ( current_user_can( 'edit_posts' ) ) : ?>
    <p>投稿者看到的內容</p>
<?php elseif ( is_user_logged_in() ) : ?>
    <p>訂閱者(一般會員)看到的內容</p>
<?php else : ?>
    <p>沒登入的訪客看到的內容</p>
<?php endif; ?>

判斷要從權限最高的開始:管理員也擁有「編輯文章」的權限,如果先判斷 edit_posts,管理員就會先被當成投稿者。

舊版文章用的是 current_user_can( 'level_10' )、level_7 這類「使用者等級」寫法,那是 WordPress 早期的機制,已經淘汰多年,請改用上面的權限名稱。

要判斷自訂角色,檢查使用者的角色清單:

PHP
$user = wp_get_current_user();
if ( in_array( 'c_business', (array) $user->roles, true ) ) {
    // 目前的使用者是「企業主」角色
}

區塊主題沒有 PHP 範本檔可以改,在「外觀 → 編輯器」的範本裡加入「短代碼」區塊,使用寫法一或寫法二的短代碼就可以。

一定要知道的限制

被隱藏的內容,搜尋引擎看不到

Google 的爬蟲不會登入你的網站,所以用短代碼包起來的內容,對搜尋引擎來說等於不存在,不會被收錄,也不會替文章加分。

  • 文章公開的部分要寫得完整、有內容,讓沒登入的讀者(和搜尋引擎)也知道這篇在講什麼。
  • 不要反過來判斷「是 Google 爬蟲就顯示全文」。給搜尋引擎和使用者看不同的內容屬於「偽裝(cloaking)」,違反 Google 的搜尋規範,網站可能被降低排名甚至移除。
  • 經營付費訂閱內容、又希望被搜尋引擎收錄的網站,Google 另外有「付費內容」的結構化資料規範,要照規範處理。

隱藏內容不等於保護檔案

短代碼只是「不把這段內容輸出到網頁上」。如果藏起來的是一個 PDF 下載連結,檔案本身還是放在 wp-content/uploads/ 裡,知道網址的人不用登入也能直接下載。真正需要保護的檔案,要用會員外掛或主機端的下載控管。

快取外掛的設定

快取外掛通常不會替登入的使用者產生快取頁面,所以這些寫法大多可以正常運作。但如果你在快取外掛裡開啟了「替登入使用者快取」之類的選項,不同角色可能會拿到同一份快取頁面,會員內容就可能被別人看到。使用這些寫法時,請確認這類選項是關閉的。

需求再複雜,就交給會員外掛

如果要做付費會員、訂閱到期、分級收費、會員專屬檔案下載,自己寫的程式會越來越難維護,這時候改用成熟的會員外掛比較省事,也比較安全。

延伸閱讀

會員網站哪些內容要公開、哪些只給會員,最好在規劃時就想清楚,才不會跟搜尋排名互相衝突。正威網路行銷是 25 年經驗的基隆網頁設計工作室,提供客製化網頁設計與 SEO 搜尋引擎優化,歡迎來聊聊。

分享這篇文章

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

發表留言

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

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