株式会社ライブキャストロゴ 株式会社ライブキャスト

久しぶりのエントリーになるのですが、たいした内容ではありませんがちょっとだけはまったので、備忘録として残しておきたいと思います。

PHPのstrpos関数は、ある文字列の中に特定の文字が含まれているかどうかチェックしたいような時に使います。

“apple”という文字列の中にpという文字が含まれているか?また、何文字目にあるか?

この例をコードにすると、

<?php
echo strpos("apple", "p");
?>

と言った感じになるかと思います。

この出力結果は

1

です。

引数は3つ指定でき、3番目の引数には何文字目から検索するかを指定できるので、文字列”apple”の2番目のpの位置をチェックすることもできます。

関数の詳細については、PHP: strpos – Manualをご参照ください。

JavaScriptで言うと、indexOf関数あたりでしょうか?

strposのはまりポイントとしては、


この関数は論理値 FALSE を返す可能性がありますが、FALSE として評価される値を返す可能性もあります。詳細については 論理値のセクションを参照してください。この関数の返り値を調べるには ===演算子 を使用してください

PHP: strpos – Manualより引用。

あたりがよく紹介されていると思いますが、
strpos: 文字列が最初に現れる場所を見つける (String 関数) – PHPプロ!マニュアル

今回私がはまったのは、


needle が文字列でない場合は、 それを整数に変換し、その番号に対応する文字として扱います。

PHP: strpos – Manualより引用。

のところでした。

カンマ区切りの文字列から数値を見付け出す、と言うような処理をかいていたのですが、とある数値の時に期待する結果にならず、異なる位置の値がリターンされていました。

その理由は、探したい数値を数値のまま指定してたからなのです。

結論から言ってしまうと、2番目の引数(needle)を文字列として調べたいのなら、明示的にキャストしないといけません。

以下に、例を示したいと思います。

sample1)

<?php
$haystack = "AA10033,01,0001";
$needle = 10033;
echo strpos($haystack, $needle);
?>

sample2)

<?php
$haystack = "1,10033,0,0001";
$needle = 10033;
echo strpos($haystack, $needle);
?>

sample3)

<?php
$haystack = "1,10033,0,0001";
$needle = 10033;
echo strpos($haystack, (string)$needle);
?>

sample1の結果

2

sample2の結果

0

sample2の結果

2

sample1では意図する結果が得られていますが、sample2ではそうはなりませんでした。
が、sample3で明示的にキャストしてやると、期待通りの結果を得ることができました。

ちなみに、JavaScriptのindexOfで同様の処理を実行すると以下のようになります。

var str1 = "AA10033,01,0001";
var str2 = "1,10033,01,0001";
var ch = 10033;
var index1 = str1.indexOf(ch);
var index2 = str1.indexOf(ch);
document.write(index1);
document.write(index2);

出力結果はいずれも、

2

になりました。
PHPとは、若干挙動が異なります。

リファレンスをしっかり読んで、基本に忠実な実装をすれば、そんなにはまるようなところでもないのですが、PHPなどでサーバサイドのプログラムを書いたり、JavaScriptでクライアント側の処理を書いたりしていると、混乱してしまいますよね。

まれに、コーディングしているとどハマったりすることもありますが、そういう時って、全く思いもしないようなところに誤りがあったりしてなかなか気付きにくいものですが、苦労して調べた結果、原因を突き止めた際には理解力が深まったような気がします。

とは言うものの、納期前のどハマりはきついですので、なるべく同じハマり方はしないように気をつけたいものです。