在php中strpos是查找字符串首次出現的位置,如果存在就返回ture或相關具體數字,沒有就返回0或false了,但本人要用它做一個wordpress關鍵詞黑名單反垃圾評論時發現一些問題,下面我們來看看。
修改主題comments-ajax.php文件
在主題目錄下的comments-ajax.php文件中,大概60行左右的位置(剛取得用戶提交的評論表單中的$_POST['author']等字段)。然後在該文件中加上下面的代碼:
代碼如下 復制代碼 /*
* @Author: vfhky 2013年09月21日22:13
* @Variable string $word: 黑名單中的關鍵詞,用戶可自行按規律進行增加或減少
* @Variable string $comment_author: 用戶提交的$_POST['author']字段值,表示昵稱
* @Variable string $comment_content: 用戶提交的$_POST['comment']字段值,表示評論內容
**/
$words = "com,cn,info,net,www,http,cc,host,代理,移動,電,國,港,器,服,醫,肥,藥,農,信,貸,日,盈,網,票,域,銷,黃,司,企,機,租,人,錢,設,購,播";
$word = explode(',', $words);
$num = count($word);
for($i=0;$i< $num ;$i++){
if (strpos($comment_author,$word[$i],0) || strpos($comment_content,$word[$i],0)){
err( __('廣告必刪,多謝理解!') );
break;
}
}
4 後記
通過上面這段簡單代碼,我們就實現了提交對評論輸入的用戶昵稱、評論內容進行了黑名單中的關鍵詞的校驗。一旦匹配到了上面的任何一個詞語,例如出現了www,那麼就提示用戶“廣告必刪,多謝理解!”,效果如下圖所示。這樣算是又給博客上了一道保險,增強了wordpress反垃圾評論的免疫力,而且還是非插件的方法實現的喲!
上面看上沒問題,但是上午 @壞 童鞋一個邪惡測試,發現了上篇文章代碼的BUG。晚上下班回來,仔細看了下代碼,發現是自己對strpos函數的片面認識,因此做個筆記Mark一下。
2 strpos函數的原型
相信大家對strpos函數並不陌生,經常在字符串的處理中能看到它的身影。strpos函數原型是:
/*
* @Para string $source: 在該字符串中進行查找[*]
* @Para mixed $target: 要查找的字符串;如若不是字符串,將被轉換為整型並被視為字符的順序值[*]
* @Para int $offset: 查找的起始位置
* @Return int/boolean: 成功則返回第一次出現的位置; 失敗返回 FALSE 值
**/
int strpos(string $source, mixed $target [, int $offset = 0 ]);
3 strpos函數的簡單測試
了解了strpos函數的原型之後,我們先來看一段簡單的測試代碼。
代碼如下 復制代碼 /*
測試結果如下圖所示:
再議wordpress反垃圾評論:都是strpos函數惹的禍
4 strpos函數的測試結果分析
上面這段代碼中有兩個不同的測試變量$test_1和$test_2,並且二者都包含了黑名單中的關鍵詞:購。但是從圖中顯示的測試結果來看,$test_1變量沒有別有效屏蔽,而變量$test_2卻被提示包含廣告詞。奧秘就在於變量$test_1和$test_2中的“購”字出現的位置就!當關鍵詞“購”出現在最前面時($test_1),strpos($test_1,$word[$i],0)函數的執行結果為0,因為“購”字在字符串“購買TT”的最前面。那麼for循環中的if語句變成了if(0){},從而不會被視為垃圾評論,這就造成了BUG。下面分別是繼續用strpos函數和使用PHP正則表達式,兩種方法來實現“wordpress關鍵詞黑名單:反垃圾評論再升級”。
5.1 正確使用strpos函數修正BUG
/*
* @Author: vfhky 2013年09月24日20:06
* @Description: 正確使用strpos函數,解決上一篇文章代碼的BUG
**/
$words = "com,cn,info,net,www,http,cc,host,代理,移動,電,國,港,器,服,醫,肥,藥,農,信,貸,日,購,播";
$word = explode(',', $words);
$num = count($word);
for($i=0;$i< $num ;$i++){
if ( (strpos($comment_author,$word[$i],0) !== false) || (strpos($comment_content,$word[$i],0) !== false) ){
err( __('廣告必刪,多謝理解!') );
break;
}
}
5.2 使用PHP正則表達式修正BUG
代碼如下 復制代碼 /*
6 函數strpos的重要提醒
使用strpos函數還需要注意的一點就是:它可能返回布爾值 FALSE,但也可能返回等同於 FALSE 的非布爾值。
例如返回整型0,浮點型值0.0,空字符串,字符串 "0",不包括任何元素的數組,不包括任何成員變量的對象,特殊類型NULL等等。
因此,應使用會檢查返回的值的類型的恆等運算符“===”來測試此函數的返回值,而不是使用簡單的等號“==”來判別。
7Update 2013.09.26 22:27
經過 @星河大帝 的提醒,可以使用數組來代替字符串,執行效率應該差不多。
7.1 使用strpos函數+數組修正BUG
$words = array("com","cn","info","net","www","http","cc","host","代理","移動","電","國","港","購");
$num = count($words);
for($i=0;$i< $num ;$i++){
if (strpos($comment_author,$words[$i],0) !== false || strpos($comment_content,$words[$i],0) !== false){
err( __('廣告必刪,多謝理解!') );
break;
}
}
7.2 使用正則式+數組修正BUG
代碼如下 復制代碼 $words = array("com","cn","info","net","www","http","cc","host","代理","移動","電","國","港","購");