strposで文字列が含まれるかどうかチェックする際には演算子に注意! (===true もしくは !==falseを使う)

PHPである文字列の中に、ある文字列が含まれるかどうかを検索するには、いくつか方法があります。

preg_match
strstr
strpos

これらの関数のどれを使っても目的は果たせるんですが、単純に文字列のチェックをするだけなら、処理時間順に比較すると
preg_match>strstr>strpos
となります。preg_matchを使うのはパフォーマンスの観点から避けるべきですね。
PHPのマニュアルサイトにも

ある文字列が他の文字列内に含まれているかどうかを調べるためだけに preg_match() を使うのは避けた方が良いでしょう。 strpos() か strstr() 関数を 使う方が速くなります。
PHP: preg_match – Manual”

とあります。

さてここからが本題。

strstr()の例

タイトル文字列の中に、特定のキーワードが含まれていたら、それを「タグ」として扱う、という処理を考えていました。

$haystack = '昨日は動物園に行きました';
 
if(strstr($haystack, '動物園')){
$tag = '動物園';
}
 
var_dump($tag);

この実行結果は、

string(9) “動物園”

となります。

strstrよりもstrposの方が若干早いということなので、代用してみると…

$haystack = '昨日は動物園に行きました';
 
if(strpos($haystack, '動物園')){
$tag = '動物園';
}
 
var_dump($tag);

これもうまくいきました。

string(9) “動物園”

これでめでたしめでたし…と思いきや、うまくいかないケースがありました。

広告

$haystack = '動物園でレッサーパンダを見ました';
 
if(strpos($haystack, '動物園')){
$tag = '動物園';
}
 
var_dump($tag);

この実行結果が、

Notice: Undefined variable: tag in C:\sandbox\strpos.php on line 11
NULL

となってしまうのです。
つまり条件が真になっていない。

それぞれの関数でそもそもどういう結果が返ってきているのかを調べると…

var_dump(strstr($haystack, '動物園'));

string(48) “動物園でレッサーパンダを見ました”

var_dump(strpos($haystack, '動物園'));

int(0)

どちらも、文字列の中で文字列(needle)が最初に現れる位置を探す関数なんですが、
strstrは、needle が最初に現れる場所を含めてそこから文字列の終わりまでを返します。
対してstrposは、needle が最初に現れる位置を探します。

ここで問題になるのは、needleが先頭に現れる場合。このとき、strposは”0″を返しますが、PHPでは通常、intの0と論理値のfalseの区別をしないので、この式の書き方だとfalseになってしまうんですね。

つまりこういう場合、strstrでシンプルに書くなら

if(strstr($haystack, '動物園')){
$tag = '動物園';
}

ですが、strposを使うならば

if(strpos($haystack, '動物園') !=0 ){

でも

if(strpos($haystack, '動物園') !==0 ){

でもなくて、

if(strpos($haystack, '動物園') !==false ){
$tag = '動物園';
}

と書く必要があったわけですね。

trueなら ===
falseなら !==
です。

About: dacelo


Leave a Reply to Anonymous Cancel reply

Your email address will not be published. Required fields are marked *