[なぞなぞ]PHPで数値を判定するのは難しいから検証してみた

2019年4月24日

はじめに

今回はいつもと気色の違う記事になります。

数値を判別する時にベストな判定はどれなのかを調べてみました。

 

環境

PHP: 7.2.6

 

PHPは曖昧

PHPの型判定が曖昧なのは有名な話です。

例えば

 '1'==1 //true

 

上のような文字型の「1」と数値型の「1」がtrueと認識されます。

 

判別式

数値を正確に判定する方法は何があるでしょうか?

以下の4パターンで調査します。

  1. ctype_digit()
  2. is_numeric()
  3. $a === intval($a)
  4. preg_match("/^[0-9]+$/", $a)
  5. is_int()

 


 

ctype_digit()

数字かどうかを調べる関数です。

与えられた文字列 text のすべての文字が 数字であるかどうかを調べます。

string text のすべての文字が 10 進数字だった場合に TRUE、そうでない場合に FALSE を返します。

https://www.php.net/manual/ja/function.ctype-digit.php

 


 

is_numeric()

変数が数字または数値形式の文字列であるかを調べる関数です。

指定した変数が数値であるかどうかを調べます。

数値または数値形式の文字列である場合に TRUE、それ以外の場合に FALSE を返します。

https://www.php.net/manual/ja/function.is-numeric.php

 


 

$a === intval($a)

論理の力押し。

intval()で数値型に変換する前と比較して同一の値であることを検証しています。

 


 

preg_match("/^[0-9]+$/",$a)

なぞの暗号、いや正規表現。

正規表現で0~9の間の文字以外が含まれている場合はエラーになります。

当然全角数字もエラーです。

 


 

is_int()

なんだか意味なく忘れていた関数です。
なお大本命な模様

変数が整数型かどうかを検査する

https://www.php.net/manual/ja/function.is-int.php

 

検証

さて今回の検証は以下になります。

  1. a
  2. 1
  3. '1'
  4. 1(全角)
  5. -1
  6. '-1'
  7. 1.1
  8. 1-1
  9. '1-1'

 

表にすると下記になります。

 

a 1 '1' 1(全角) -1 '-1' 1.1 1-1 '1-1'
ctype_digit()
is_numeric()
$a === intval($a)
preg_match("/^[0-9]+$/",$a)
is_int()

 

検証用のPHPは以下の通りです。
興味のある方は、自分でも検証してどーぞー

<?php $number = 1 ?>
[ctype_digit()]
<?php var_dump(ctype_digit($number))  ?>
[is_numeric()]
<?php var_dump(is_numeric($number))  ?>
[$a === intval($a)	]
<?php var_dump($number === intval($number)	)  ?>
[preg_match("/^[0-9]+$/",$a)]
<?php var_dump(preg_match("/^[0-9]+$/",$number))  ?>
[is_int()]
<?php var_dump(is_int($number))  ?> 

 

さてレッツ検証です!

 

結果

速攻で結果発表です。

 

a 1 '1' 1(全角) -1 '-1' 1.1 1-1 '1-1'
ctype_digit() × × × × × × × ×
is_numeric() × × ×
$a === intval($a) × × × × × ×
preg_match("/^[0-9]+$/",$a) × × × × × ×
is_int()
× × × × × ×

○:true
×:false

 


 

ctype_digit の結果がおかしい

「a」ならまだしも「1」がfalseなのは違和感ありますね。と思ったら下記の記述が・・・

この関数を活用するには string を渡さなければなりません。 たとえば integer を渡すと、期待する結果にならない可能性があります。

 

URLの数値バラメーターを受け取った時に、フレームワークやライブラリが文字列として受け取ってしまうなら、これを使う感じですかね。

SQLインジェクション対策になりそうです。


 

is_numeric は曖昧

取説どおりの仕様ですね。
用途によっては一芸特化してるイメージです。

 


 

意外と優秀な $a === intval($a)

intvalするとはいえ、意外と優秀です。

===演算のおかげ?

完全な数値型を求めるならこれですね。

 


 

整数を嗅ぎ分ける preg_match("/^[0-9]+$/",$a)

is_int の存在が判明してからは、整数取得はis_intで良いんじゃないか感があります。

'1'も含めた、整数を求めるならこれですかねえ


 

割と想定どおりな動きをする is_int()

整数だけを取得したければこれが良さそうです。

 

 

まとめ

検証の結果で、管理人はまた混乱してきました。

完全に数字型のみを取得したいなら「$a === intval($a)」を使うのが良さげです。

整数を取得したいなら「is_int()」が良さそうです。

 

まだ検証が必要そうです。

こうして型沼にハマって行きます・・・

 

今日はこの辺でー

  • この記事を書いた人

カバノキ

印刷会社のWEB部隊に所属してます。 WEB制作に携わってから、もう時期10年になります。 普段の業務では、PHPをメインにサーバーサイドの言語を扱っています。 最近のお気に入りはJavascriptです。 Vue.jsを狂喜乱舞しながら、社内に布教中です。

-PHP
-, , ,