- 2007年12月 6日 19:20
- PHP
非常に参考になるエントリ「そのis_numeric()は適切ですか?」を読んで。PHPで数値判定する機会は大分あると思う。特にフォームで入力された電話番号やらなんやらで。その判定方法を間違ってしまうと、思わぬバグが発生してしまうという話。
is_numericのなにがいけないのか
今まで僕は文字列の判定には preg_match() を使っていました。そりゃもう使い果たしています。正規表現が大好きなので。でも、PHPのパフォーマンスチューニングをしようと思っていろいろと文献を見ていると正規表現は遅いのでなるべく他の関数に置き換えるという意見を目にし、あまり考えずに is_numeric() を使ってベンチマークを取ろうと思っていた矢先に、先のエントリを目にし慌ててマニュアルを読み直しました。
指定した変数が数値であるかどうかを調べます。数値文字列は以下の要素から なります。(オプションの)符号、任意の数の数字、(オプションの)小数部、 そして(オプションの)指数部。つまり、+0123.45e6 は数値として有効な値です。16 進表記(0xFF)も 認められますが、この場合は符号や小数部、指数部を含めることはできません。
オーノー。10進数以外にも数値はあるじゃねーか。
やっぱりここは /^[0-9]+$/ というオーソドックスな方法で判定すべきですね。反省。
他に数値判定できる方法は?
is_int() やMathの数学関数にもいくつか数値判定をしてくるものはありますが、10進数に限った判定をしてくれる関数はありませんでした。
特に is_int() は、変数が数値もしくは数値文字列の場合 (フォームからの入力の場合は 常に文字列となります) 、is_numeric() を使用する必要があります。
ということで、フォームからの入力値に関しては注意が必要です。
- Newer: 携帯電話のキャッシュをコントロールする方法
- Older: MySQLのAUTO_INCREMENTで生成された値を簡単に取得する方法
Comments:2
- ogi 2007年12月 7日 01:12
/^[0-9]+$/ だったら、ctype_digit() のが早いです。
それだけの関数なので融通きかず、使えるところは限られてしまいますが。。。
この正規表現もctype_digitも、010といった文字列が通過して、頭が0で始まるものは8進数と解釈するので、8進数の010が10進数の8になっちゃったりするのでときどき危険です。その他の判定方法としては、PHP5.2以降だとフィルタ関数で、FILTER_VALIDATE_INT でチェックする、というのもアリです。まだ新しいのでそんなに使われてないですが。
filter_var("35", FILTER_VALIDATE_INT);
とかやると、10進数の数字であれば、数字に変換して返してくれて、そうでない場合は、falseを返します。if (false === filter_var($n, FILTER_VALIDATE_INT)) {
error_log("エラー");
}
って感じです。
http://php.net/manual/ja/ref.filter.php
http://phpro.org/tutorials/Filtering-Data-with-PHP.html#4- ZARU 2007年12月 7日 09:17
貴重な情報ありがとうございます。
ctype_digit()という関数初めて知りました…。PHPはいっぱい関数がありますね。
他にも http://jp2.php.net/manual/ja/ref.ctype.php 正規表現の代わりに使えそうな関数があるので、検証してみようと思います。PHP5も、やっと広がってきた感じがあるので積極的に使っていこうと思います。
Trackbacks:0
- TrackBack URL for this entry
- http://blog.tofu-kun.org/mt-tb.cgi/355
- Listed below are links to weblogs that reference
- PHPで数値判定する時はご注意を from Webプログラマー+WebデザイナーなZARU日記
