0%

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

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

WordPress 限制每篇文章只能留言一次:用程式碼防止重複留言

plesk增加gzip壓縮

辦「留言抽獎」「留言分享心得」這類活動時,常會遇到同一個人連續留好幾則,想多拿幾次抽獎機會。這時就需要「每個人在同一篇文章只能留言一次」的規則。

WordPress 內建只會擋「內容完全一樣的重複留言」和「短時間內連續留言」,換幾個字就能再留,沒有「每人一則」的功能。下面用一段程式碼做到。

怎麼判斷是「同一個人」?

  • 有登入的會員:用會員帳號判斷,最準確。
  • 沒登入的訪客:用留言時填的電子郵件判斷。
  • 為什麼不用 IP 判斷:同一間公司、學校,或同一家電信的手機網路,常常很多人共用同一個對外 IP,用 IP 判斷會誤擋不同的人;反過來,同一個人換個網路就又能留言。所以這裡不用 IP。

程式碼

加到子主題的 functions.php,或用 Code Snippets 外掛新增:

PHP
add_filter( 'preprocess_comment', function ( $commentdata ) {
    // 只檢查一般留言(不含 Pingback、Trackback)
    $type = isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '';
    if ( ! in_array( $type, array( '', 'comment' ), true ) ) {
        return $commentdata;
    }

    // 管理員、編輯不受限制
    if ( current_user_can( 'moderate_comments' ) ) {
        return $commentdata;
    }

    // 回覆別人的留言不受限制(想連回覆都限制,就把這段刪掉)
    if ( ! empty( $commentdata['comment_parent'] ) ) {
        return $commentdata;
    }

    $args = array(
        'post_id' => (int) $commentdata['comment_post_ID'],
        'parent'  => 0,
        'status'  => 'all', // 已核准與待審核的都算
        'count'   => true,
    );

    $user_id = get_current_user_id();
    if ( $user_id ) {
        $args['user_id'] = $user_id;
    } elseif ( ! empty( $commentdata['comment_author_email'] ) ) {
        $args['author_email'] = $commentdata['comment_author_email'];
    } else {
        return $commentdata;
    }

    if ( get_comments( $args ) > 0 ) {
        wp_die(
            '這篇文章每個人只能留言一次喔!您的留言已經送出過了(可能還在等待審核)。',
            '已經留言過了',
            array( 'response' => 409, 'back_link' => true )
        );
    }

    return $commentdata;
} );

程式碼在做什麼?

  • preprocess_comment 會在留言存進資料庫之前執行,發現已經留過言,就用 wp_die() 顯示提示訊息,留言不會被儲存。
  • 用 get_comments() 查詢「這篇文章裡,這個帳號或這個電子郵件留過幾則」,WordPress 會用安全的方式組合查詢,不用自己寫 SQL。
  • 'status' => 'all' 代表「已核准」和「待審核」的留言都算,避免留言還在審核中,對方又重複送出。被你標成垃圾留言或丟進垃圾桶的不算。
  • 有審核留言權限的管理員、編輯不受限制,站長可以在同一篇文章回覆很多次。
  • 回覆別人的留言預設不受限制,這樣留言者還能回應你的回覆。只想限制「第一層」的留言,保留這段就好。
  • 錯誤訊息的狀態碼 409,跟 WordPress 內建擋重複留言時用的一樣;back_link 會在訊息下方顯示「返回」連結。

只想限制特定幾篇文章

通常只有活動文章需要這個規則。在程式碼一開頭($type 那一行的上面)加上這段,就只會套用在指定的文章:

PHP
    // 只限制這幾篇文章(填文章 ID)
    $limited_posts = array( 123, 456 );
    if ( ! in_array( (int) $commentdata['comment_post_ID'], $limited_posts, true ) ) {
        return $commentdata;
    }

文章 ID 在後台編輯文章時,網址列裡 post= 後面的數字就是。

舊版寫法為什麼不能用

這篇文章舊版的程式碼,是直接把留言者填的名稱、電子郵件接進 SQL 查詢指令裡。這會造成 SQL Injection(資料隱碼攻擊) 漏洞:有心人只要在「名稱」欄位輸入特殊的字元與指令,就有機會改變查詢的內容,讀取甚至破壞你的資料庫。

另外,舊寫法用「名稱相同」判斷同一個人,兩個不同的訪客都叫「小明」,第二個人就不能留言了;再加上 IP 判斷,同一間公司的同事也會互相擋到。如果你的網站還在用舊版程式碼,請盡快換成上面的寫法。

這個做法的限制

  • 換一個電子郵件就能再留言:沒登入的訪客填什麼信箱,網站無法驗證。想要嚴格的一人一次,要搭配「設定 → 討論」裡「使用者必須註冊並登入才能發佈留言」的選項,只讓會員留言。
  • 活動結算還是要人工檢查:抽獎前把留言匯出或看過一遍,確認有沒有明顯是同一個人用不同信箱重複參加。
  • 垃圾留言還是要另外擋:這段只限制次數,不會判斷內容是不是廣告,防垃圾留言的做法請看延伸閱讀的第一篇。

延伸閱讀

活動留言的規則事先想周到,後面的抽獎、統計才不會一團亂。正威網路行銷是 25 年經驗的基隆網頁設計工作室,提供客製化網頁設計,網站需要特別的留言或活動功能,歡迎來聊聊。

分享這篇文章

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

發表留言

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

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