PHP でフォームデータを数値入力チェックする方法

はじめに

実務にて、フォームデータを数値チェックするバリデーション(入力値の検証)を実装する作業があり、それを解決した情報になります。Web 開発の初心者、初学者の方にもわかりやすいように、ソースコードを編集してサンプルを公開しています、ご参考になれば幸いです。

検証環境

サンプル

  • GitHub

解説

数値チェックする方法が多いので、一目でわかるように下記のような比較表を作成しました。

比較表だけドォーン!と見せられても理解できないと思うので、各チェック方法の詳細を説明していきます。

ctype_digit

ctype_digit で、数値形式の文字列(10 進数)かどうかを検証するやり方です。

ctype_digit('1234');       // bool(true)
ctype_digit('0123');       // bool(true)
ctype_digit('0x1A');       // bool(false)
ctype_digit('0b11111111'); // bool(false)
ctype_digit('1_234_567');  // bool(false)

ctype_digit は、下記のマニュアルからの引用を見てわかる通り、整数を渡すと ASCII 値になります

-128 から 255 までの int を渡すと、ひとつの文字の ASCII 値とみなします (負の値には 256 を足して、拡張 ASCII の範囲に収まるようにします)。 それ以外の整数値は、10 進数を含む文字列とみなします。

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

ASCII 値が 48 〜 57(’0′ – ‘9’)は true を返し、それ以外は false を返します。

ctype_digit(47); // bool(false)
ctype_digit(48); // bool(true)
ctype_digit(57); // bool(true)
ctype_digit(58); // bool(false)

また、下記のように、負の符号が付いた数字やピリオドが入った小数点を含んだ数字は false になります。使い所に気を付けましょう。

ctype_digit('-1');  // bool(false)
ctype_digit('1.1'); // bool(false)

ctype_digit + strval

ctype_digit で、数値も受け入れたい場合、下記のように strval と組み合わせたやり方があります。

ctype_digit(strval(1234));         // bool(true)
ctype_digit(strval(0123));         // bool(true)
ctype_digit(strval(0x1A));         // bool(true)
ctype_digit(strval(0b11111111));   // bool(true)
ctype_digit(strval(1_234_567));    // bool(true)
ctype_digit(strval('1234'));       // bool(true)
ctype_digit(strval('0123'));       // bool(true)
ctype_digit(strval('0x1A'));       // bool(false)
ctype_digit(strval('0b11111111')); // bool(false)
ctype_digit(strval('1_234_567'));  // bool(false)

型キャストした場合も同じです。

ctype_digit((string)1234);          // bool(true)
ctype_digit((string)0123);          // bool(true)
ctype_digit((string)0x1A);          // bool(true)
ctype_digit((string)0b11111111);    // bool(true)
ctype_digit((string)1_234_567);     // bool(true)
ctype_digit((string)'1234');        // bool(true)
ctype_digit((string)'0123');        // bool(true)
ctype_digit((string)'0x1A');        // bool(false)
ctype_digit((string)'0b11111111')); // bool(false)
ctype_digit((string)'1_234_567');   // bool(false)

is_int

is_int で、整数 かどうかを検証するやり方です。

is_int(1234);       // bool(true)
is_int(0123);       // bool(true)
is_int(0x1A);       // bool(true)
is_int(0b11111111); // bool(true)
is_int(1_234_567);  // bool(true)

is_int は、下記のマニュアルからの引用を見てわかる通り、数値か数値形式の文字列かを判断したい場合には不適切です。

変数が数値か数値形式の文字列かを判断したい場合 (フォームからの入力の場合は 常に文字列となります) 、is_numeric() を使用する必要があります。

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

PHP がサポートする整数型の最小値と最大値は、整数型のバイト数によって変わることに気を付けましょう。PHP_INT_SIZE で確認することができます。

PHP_INT_SIZE; // 4 byte(32 bit)

is_int(2147483647);          // bool(true)
is_int(2147483648);          // bool(false)
is_int(9223372036854775807); // bool(false)
is_int(9223372036854775808); // bool(false)
PHP_INT_SIZE; // 8 byte(64 bit)

is_int(2147483647);          // bool(true)
is_int(2147483648);          // bool(true)
is_int(9223372036854775807); // bool(true)
is_int(9223372036854775808); // bool(false)

is_float

is_float で、float かどうかを検証するやり方です。

is_float(1.234);     // bool(true)
is_float(1.2e3);     // bool(true)
is_float(7E-10);     // bool(true)
is_float(1_234.567); // bool(true)

is_float は、下記のマニュアルからの引用を見てわかる通り、数値か数値形式の文字列かを判断したい場合には不適切です。

変数が数値か数値形式の文字列かを判断したい場合 (フォームからの入力の場合は 常に文字列となります) 、is_numeric() を使用する必要があります。

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

is_numeric

is_numeric で、数値か数値形式の文字列かどうかを検証するやり方です。

is_numeric(1234);         // bool(true)
is_numeric(0123);         // bool(true)
is_numeric(0x1A);         // bool(true)
is_numeric(0b11111111);   // bool(true)
is_numeric(1_234_567);    // bool(true)
is_numeric('1234');       // bool(true)
is_numeric('0123');       // bool(true)
is_numeric('0x1A');       // bool(false)
is_numeric('0b11111111'); // bool(false)
is_numeric('1_234_567');  // bool(false)

下記のように、文字列が数字から始まっていない場合でも true になります。numeric(数字, 数値)という言葉の定義と実際の動作が少し違うので、使い所に気を付けましょう。

is_numeric('.1');  // bool(true)
is_numeric('+1');  // bool(true)
is_numeric('-1');  // bool(true)
is_numeric(' 11'); // bool(true)

preg_match

preg_matchPCRE 正規表現構文 で半角数字かどうかのマッチングを行うやり方です。

preg_match('/\A\d+\z/', 1234);         // int(1)
preg_match('/\A\d+\z/', 0x1A);         // int(1)
preg_match('/\A\d+\z/', 0b11111111);   // int(1)
preg_match('/\A\d+\z/', 1_234_567);    // int(1)
preg_match('/\A\d+\z/', '1234');       // int(1)
preg_match('/\A\d+\z/', '0123');       // int(1)
preg_match('/\A\d+\z/', '0x1A');       // int(0)
preg_match('/\A\d+\z/', '0b11111111'); // int(0)
preg_match('/\A\d+\z/', '1_234_567');  // int(0)

filter_var(FILTER_VALIDATE_INT)

filter_var検証フィルタFILTER_VALIDATE_INT に指定して、整数かどうかをフィルタリングするやり方です。

filter_var(1234, FILTER_VALIDATE_INT);       // int(1234)
filter_var(0123, FILTER_VALIDATE_INT);       // int(83)
filter_var(0x1A, FILTER_VALIDATE_INT);       // int(26)
filter_var(0b11111111, FILTER_VALIDATE_INT); // int(255)
filter_var(1_234_567, FILTER_VALIDATE_INT);  // int(1234567)

下記の場合でも int(1) になります、使い所に気を付けましょう。

filter_var(' 1 ', FILTER_VALIDATE_INT); // int(1)
filter_var('+1', FILTER_VALIDATE_INT);  // int(1)

filter_var(FILTER_VALIDATE_FLOAT)

filter_var の 検証フィルタFILTER_VALIDATE_FLOAT に指定して、float かどうかをフィルタリングするやり方です。

filter_var(1.234, FILTER_VALIDATE_FLOAT);     // float(1.234)
filter_var(1.2e3, FILTER_VALIDATE_FLOAT);     // float(1200)
filter_var(7E-10, FILTER_VALIDATE_FLOAT);     // float(7.0E-10)
filter_var(1_234.567, FILTER_VALIDATE_FLOAT); // float(1234.567)

下記の場合でも int(1) になります、使い所に気を付けましょう。

filter_var(' 1.1 ', FILTER_VALIDATE_FLOAT); // int(1)
filter_var('+1.1', FILTER_VALIDATE_FLOAT);  // int(1)

まとめ

やり方がたくさんあって何を使ったら良いのか混乱してしまいそうですが、癖を理解して、場合に応じて柔軟に使い分ければ大丈夫です。

例えば、フォームデータが整数の場合は、ctype_digit を使います。負の数、小数を含む場合は is_numeric を使います、文字列がピリオドやスペースから始まるのを許容できない場合は、入力値を整形、又はフィルタリングするなどの工夫をすれば良いだけです。

以上です。

おわりに

サンプルのソースコードを再利用する際は、要件定義やコーディング規約にお気を付けください。