PHPで「整数かどうか」を判定するときは、まず 値の型を見たいのか、それとも 文字列の中身を見たいのか を分けて考える必要があります。
たとえば、次の2つは意味が違います。
123
これは整数型の値です。
一方で、次の値は見た目は数字ですが、PHP上では文字列です。
"123"
フォーム入力、URLパラメータ、POSTデータ、GETデータなどから受け取る値は、多くの場合 "123" のような文字列です。
そのため、Web開発でよく問題になるのは、文字列の中身が整数として妥当かどうか の判定です。
整数判定でよく使う関数の違い
PHPには整数判定に使えそうな関数がいくつかあります。
代表的なものは次のとおりです。
| 関数・方法 | 主な用途 |
|---|---|
is_int() | 値の型が整数か判定する |
ctype_digit() | 文字列が半角数字だけで構成されているか判定する |
is_numeric() | 数値として扱える文字列か判定する |
filter_var() | 整数として妥当か検証する |
preg_match() | 正規表現で独自ルールに沿って判定する |
(int) / intval() | 値を整数に変換する |
それぞれ役割が違うため、使いどころを間違えると、意図しない値を通してしまう可能性があります。
is_int() は文字列の整数判定には使えない
is_int() は型を判定する関数
is_int() は、値の型が int かどうかを判定する関数です。
var_dump(is_int(123)); // true
var_dump(is_int("123")); // false
123 は整数型なので true になります。
しかし、"123" は文字列なので false になります。
つまり、is_int() は 文字列の中身が整数っぽいかどうか を見る関数ではありません。
フォームやURLパラメータでは注意が必要
たとえば、URLに次のようなパラメータがあったとします。
?id=123
PHPでは次のように受け取ることが多いです。
$id = $_GET['id'] ?? '';
このとき $id の中身は、多くの場合 "123" という文字列です。
そのため、次のように書いても期待どおりには動きません。
$id = $_GET['id'] ?? '';
if (is_int($id)) {
echo "整数です";
}
$id は文字列なので、is_int($id) は基本的に false になります。
したがって、フォームやURLパラメータの整数判定では、is_int() ではなく、文字列の内容を検証する方法を使う必要があります。
ctype_digit() は半角数字だけの判定に便利
ctype_digit() の基本
ctype_digit() は、文字列が 半角数字だけ で構成されているかを判定します。
var_dump(ctype_digit("123")); // true
var_dump(ctype_digit("00123")); // true
var_dump(ctype_digit("0")); // true
すべての文字が数字であれば true になります。
一方で、数字以外の文字が含まれている場合は false です。
var_dump(ctype_digit("-123")); // false
var_dump(ctype_digit("+123")); // false
var_dump(ctype_digit("12.3")); // false
var_dump(ctype_digit("1e3")); // false
var_dump(ctype_digit("abc")); // false
var_dump(ctype_digit(" 123 ")); // false
var_dump(ctype_digit("")); // false
ctype_digit() が向いているケース
ctype_digit() は、次のような値を許可したい場合に向いています。
"0"
"1"
"123"
"00123"
たとえば、URLパラメータのIDが半角数字だけかどうかを確認したい場合は、次のように書けます。
$id = $_GET['id'] ?? '';
if (!ctype_digit($id)) {
http_response_code(400);
exit('Invalid ID');
}
$id = (int) $id;
このコードでは、"123" は通りますが、"abc"、"12.3"、"-1" などは拒否されます。
ctype_digit() はマイナスを許可しない
ctype_digit() は数字だけを見る関数なので、マイナス記号は許可されません。
ctype_digit("-123"); // false
したがって、負の整数も許可したい場合には、ctype_digit() ではなく、filter_var() や正規表現を使う方が適しています。
ctype_digit() は先頭ゼロを許可する
ctype_digit() は、文字列が数字だけであれば true を返します。
そのため、次のような文字列も通ります。
ctype_digit("00123"); // true
"00123" を許可してよい場合は問題ありません。
しかし、IDやページ番号などで 先頭ゼロを禁止したい 場合は、ctype_digit() だけでは不十分です。
その場合は、正規表現で判定するのがわかりやすいです。
$value = "00123";
if (preg_match('/^(0|[1-9][0-9]*)$/', $value) === 1) {
echo "0以上の整数です";
} else {
echo "不正な値です";
}
この正規表現では、"0" は許可し、"123" も許可しますが、"00123" は拒否します。
is_numeric() は整数判定には広すぎる
is_numeric() は数値全般を判定する
is_numeric() は、値が数値または数値文字列かどうかを判定する関数です。
var_dump(is_numeric("123")); // true
var_dump(is_numeric("-123")); // true
var_dump(is_numeric("+123")); // true
var_dump(is_numeric("12.3")); // true
var_dump(is_numeric("1e3")); // true
ここで注意したいのは、is_numeric() は整数だけではなく、小数や指数表記も true にする という点です。
is_numeric("12.3"); // true
is_numeric("1e3"); // true
"1e3" は数値としては 1000 と解釈できます。
しかし、文字列の見た目としては、一般的な整数文字列とは言いにくいです。
整数だけを許可したい場合には不向き
次のようなコードは、一見すると整数判定に見えます。
$value = $_GET['id'] ?? '';
if (is_numeric($value)) {
$id = (int) $value;
}
しかし、このコードでは "12.9" や "1e3" も通ってしまいます。
$value = "12.9";
if (is_numeric($value)) {
var_dump((int) $value); // int(12)
}
"12.9" が 12 に変換されるため、意図しない値を受け入れてしまう可能性があります。
そのため、整数だけを許可したい場合に is_numeric() を使うのは避けた方が安全です。
PHP 8.0以降では前後の空白にも注意
PHP 8.0以降では、is_numeric() は前後に空白がある数値文字列も true と判定します。
var_dump(is_numeric("123")); // true
var_dump(is_numeric(" 123 ")); // true
厳密に「空白なしの整数文字列」を判定したい場合、is_numeric() はさらに不向きです。
filter_var() は整数として妥当か検証できる
FILTER_VALIDATE_INT の基本
文字列が整数として妥当か確認したい場合、filter_var() と FILTER_VALIDATE_INT を使う方法があります。
var_dump(filter_var("123", FILTER_VALIDATE_INT)); // int(123)
var_dump(filter_var("-123", FILTER_VALIDATE_INT)); // int(-123)
var_dump(filter_var("+123", FILTER_VALIDATE_INT)); // int(123)
整数として妥当な場合は、int 型に変換された値が返ります。
一方で、整数として妥当でない場合は false が返ります。
var_dump(filter_var("12.3", FILTER_VALIDATE_INT)); // false
var_dump(filter_var("1e3", FILTER_VALIDATE_INT)); // false
var_dump(filter_var("abc", FILTER_VALIDATE_INT)); // false
判定は !== false で行う
filter_var() を使うときに特に注意したいのが、戻り値の判定です。
$result = filter_var("0", FILTER_VALIDATE_INT);
var_dump($result); // int(0)
"0" は正しい整数です。
しかし、PHPでは 0 は条件式の中で false 的に扱われます。
そのため、次のような書き方は危険です。
if (filter_var($value, FILTER_VALIDATE_INT)) {
echo "整数です";
}
この書き方だと、"0" のときに条件が成立しません。
正しくは、次のように !== false で判定します。
$result = filter_var($value, FILTER_VALIDATE_INT);
if ($result !== false) {
echo "整数です";
} else {
echo "整数ではありません";
}
filter_var() は前後の空白を許可する
FILTER_VALIDATE_INT は、検証前に文字列の前後の空白を取り除きます。
そのため、次のような文字列も整数として通ります。
var_dump(filter_var(" 123 ", FILTER_VALIDATE_INT)); // int(123)
これは ctype_digit() とは違う挙動です。
var_dump(ctype_digit(" 123 ")); // false
前後の空白を許可したくない場合は、filter_var() だけでは仕様に合わない可能性があります。
filter_var() はプラス記号を許可する
FILTER_VALIDATE_INT では、+123 も整数として扱われます。
var_dump(filter_var("+123", FILTER_VALIDATE_INT)); // int(123)
仕様として +123 を許可してよいなら問題ありません。
しかし、「半角数字だけ」「符号なしの整数だけ」を許可したい場合は、filter_var() よりも ctype_digit() や正規表現の方が向いています。
filter_var() は先頭ゼロに注意が必要
FILTER_VALIDATE_INT では、通常 "00123" のような先頭ゼロ付きの整数文字列は false になります。
var_dump(filter_var("00123", FILTER_VALIDATE_INT)); // false
一方で、ctype_digit() では true になります。
var_dump(ctype_digit("00123")); // true
そのため、先頭ゼロを許可したい場合は ctype_digit()、先頭ゼロを禁止したい場合は filter_var() や正規表現が候補になります。
filter_var() で範囲指定する方法
min_range と max_range を使う
filter_var() の便利な点は、整数かどうかだけでなく、範囲も一緒にチェックできることです。
$value = "25";
$result = filter_var($value, FILTER_VALIDATE_INT, [
'options' => [
'min_range' => 1,
'max_range' => 100,
],
]);
if ($result !== false) {
echo "1〜100の整数です";
} else {
echo "不正な値です";
}
このコードでは、1 以上 100 以下の整数だけが許可されます。
ページ番号の判定例
ページ番号を受け取る場合は、1以上の整数だけを許可することが多いです。
$page = $_GET['page'] ?? '1';
$page = filter_var($page, FILTER_VALIDATE_INT, [
'options' => [
'min_range' => 1,
],
]);
if ($page === false) {
$page = 1;
}
不正なページ番号が渡された場合は、1ページ目に戻すような処理にできます。
年齢や数量の判定例
年齢や購入数量のように、最小値と最大値を決めたい場合にも filter_var() は便利です。
$quantity = $_POST['quantity'] ?? '';
$quantity = filter_var($quantity, FILTER_VALIDATE_INT, [
'options' => [
'min_range' => 1,
'max_range' => 99,
],
]);
if ($quantity === false) {
exit('数量が不正です');
}
このように書けば、整数判定と範囲チェックをまとめて行えます。
正規表現を使うと細かいルールを決められる
正規表現が向いているケース
正規表現は、整数の表記ルールを細かく決めたいときに便利です。
たとえば、次のような条件を指定できます。
マイナスを許可するか
プラスを許可するか
先頭ゼロを許可するか
0を許可するか
空白を許可するか
1以上に限定するか
ctype_digit() や filter_var() では微妙に合わない仕様でも、正規表現なら明確に表現できます。
半角数字だけを許可する
if (preg_match('/^\d+$/', $value) === 1) {
echo "半角数字だけです";
}
この正規表現では、次のような値が通ります。
"0"
"123"
"00123"
ただし、先頭ゼロも許可されます。
0以上の整数で先頭ゼロを禁止する
if (preg_match('/^(0|[1-9][0-9]*)$/', $value) === 1) {
echo "0以上の整数です";
}
この場合、次のようになります。
"0" OK
"1" OK
"123" OK
"00123" NG
"01" NG
1以上の整数だけを許可する
IDやページ番号などでは、0 を許可したくない場合があります。
その場合は次のように書けます。
if (preg_match('/^[1-9][0-9]*$/', $value) === 1) {
echo "1以上の整数です";
}
この場合、次のようになります。
"1" OK
"123" OK
"0" NG
"00123" NG
"-1" NG
"+1" NG
負の整数も許可する
負の整数も許可したい場合は、次のように書けます。
if (preg_match('/^-?\d+$/', $value) === 1) {
echo "整数です";
}
この場合、次のようになります。
"123" OK
"-123" OK
"0" OK
"12.3" NG
"abc" NG
ただし、この正規表現では "00123" や "-00123" も通ります。
負の整数も許可し、先頭ゼロは禁止する
より厳密にするなら、次のように書きます。
if (preg_match('/^-?(0|[1-9][0-9]*)$/', $value) === 1) {
echo "整数です";
}
この場合、次のようになります。
"0" OK
"10" OK
"-10" OK
"001" NG
"-001" NG
(int) や intval() は判定ではなく変換
キャストは入力チェックではない
(int) や intval() は、値を整数に変換するためのものです。
整数として妥当かどうかを確認するためのものではありません。
var_dump((int) "123"); // int(123)
var_dump((int) "123abc"); // int(123)
var_dump((int) "12.9"); // int(12)
var_dump((int) "abc"); // int(0)
このように、明らかに整数文字列ではない値でも、強制的に整数へ変換されます。
変換前に必ず検証する
次のようなコードはよく見かけますが、注意が必要です。
$id = (int) $_GET['id'];
このコードでは、次のような値も変換されてしまいます。
"123abc" → 123
"12.9" → 12
"abc" → 0
意図しない値を受け入れないためには、まず検証してから変換します。
$id = $_GET['id'] ?? '';
if (!ctype_digit($id)) {
http_response_code(400);
exit('Invalid ID');
}
$id = (int) $id;
Webアプリケーションでは、変換より先に検証する という考え方が重要です。
全角数字を受け付ける場合の注意点
全角数字はそのままだと通らない
日本語のフォームでは、ユーザーが全角数字を入力することがあります。
123
しかし、ctype_digit() では通常、全角数字は false になります。
var_dump(ctype_digit("123")); // false
半角数字のみを許可する仕様なら、このまま拒否して問題ありません。
全角数字を半角に変換してから判定する
全角数字も受け付けたい場合は、先に半角へ変換してから判定します。
$value = $_POST['age'] ?? '';
$value = mb_convert_kana($value, 'n', 'UTF-8');
if (!ctype_digit($value)) {
exit('年齢が不正です');
}
$age = (int) $value;
mb_convert_kana() を使うと、次のように変換できます。
"123" → "123"
日本語サイトのフォームでは、全角数字を許可するかどうかを仕様として決めておくとよいです。
空文字や未入力の扱い
空文字は整数ではない
ctype_digit() では、空文字は false になります。
var_dump(ctype_digit("")); // false
未入力をエラーにしたい場合は、次のように分けて判定するとわかりやすいです。
$value = $_POST['age'] ?? '';
if ($value === '') {
exit('入力してください');
}
if (!ctype_digit($value)) {
exit('整数で入力してください');
}
未入力時にデフォルト値を使う場合
ページ番号のように、未入力ならデフォルト値を使いたいケースもあります。
$value = $_GET['page'] ?? '';
if ($value === '') {
$page = 1;
} elseif (ctype_digit($value)) {
$page = (int) $value;
} else {
exit('ページ番号が不正です');
}
このように、未入力と不正入力を分けて扱うと、処理の意図が明確になります。
判定結果の比較表
代表的な値について、各関数の結果を比較すると次のようになります。
| 値 | ctype_digit() | is_numeric() | filter_var($v, FILTER_VALIDATE_INT) |
|---|---|---|---|
"123" | true | true | int(123) |
"00123" | true | true | false |
"0" | true | true | int(0) |
"-123" | false | true | int(-123) |
"+123" | false | true | int(123) |
"12.3" | false | true | false |
"1e3" | false | true | false |
" 123 " | false | true | int(123) |
"abc" | false | false | false |
"" | false | false | false |
"123abc" | false | false | false |
この表からわかるように、同じ「整数判定」に見えても、関数によって許可する範囲がかなり違います。
実務での使い分け
半角数字だけを許可したい場合
半角数字だけを許可したい場合は、ctype_digit() がシンプルです。
if (ctype_digit($value)) {
echo "半角数字だけです";
}
許可される値の例は次のとおりです。
"0"
"123"
"00123"
拒否される値の例は次のとおりです。
"-123"
"+123"
"12.3"
"1e3"
" 123 "
"abc"
1以上のIDとして扱いたい場合
IDのように、1以上の整数だけを許可したい場合は、正規表現を使うと明確です。
$id = $_GET['id'] ?? '';
if (!preg_match('/^[1-9][0-9]*$/', $id)) {
http_response_code(400);
exit('Invalid ID');
}
$id = (int) $id;
この場合、"1" や "123" は通りますが、"0"、"00123"、"-1"、"+1" は拒否されます。
0以上の整数として扱いたい場合
0 を許可し、先頭ゼロは禁止したい場合は、次の正規表現が使えます。
if (preg_match('/^(0|[1-9][0-9]*)$/', $value) === 1) {
echo "0以上の整数です";
}
この判定では、"0" は通りますが、"00" や "001" は拒否されます。
マイナスも許可したい場合
マイナスも許可したい場合は、filter_var() が使いやすいです。
$value = $_POST['value'] ?? '';
$int = filter_var($value, FILTER_VALIDATE_INT);
if ($int === false) {
exit('整数ではありません');
}
ただし、filter_var() は "+123" や " 123 " も許可します。
それらを拒否したい場合は、正規表現を使います。
if (preg_match('/^-?(0|[1-9][0-9]*)$/', $value) === 1) {
echo "整数です";
}
範囲指定もしたい場合
整数かどうかだけでなく、最小値や最大値も決めたい場合は、filter_var() が便利です。
$age = filter_var($_POST['age'] ?? '', FILTER_VALIDATE_INT, [
'options' => [
'min_range' => 0,
'max_range' => 150,
],
]);
if ($age === false) {
exit('年齢が不正です');
}
年齢、数量、ページ番号、表示件数などでは、範囲指定を一緒に行うと安全です。
おすすめの自作関数
半角数字だけか判定する関数
function isDigitString(string $value): bool
{
return ctype_digit($value);
}
使用例です。
var_dump(isDigitString("123")); // true
var_dump(isDigitString("00123")); // true
var_dump(isDigitString("-123")); // false
1以上の整数文字列か判定する関数
function isPositiveIntegerString(string $value): bool
{
return preg_match('/^[1-9][0-9]*$/', $value) === 1;
}
使用例です。
var_dump(isPositiveIntegerString("1")); // true
var_dump(isPositiveIntegerString("123")); // true
var_dump(isPositiveIntegerString("0")); // false
var_dump(isPositiveIntegerString("00123")); // false
0以上の整数文字列か判定する関数
function isNonNegativeIntegerString(string $value): bool
{
return preg_match('/^(0|[1-9][0-9]*)$/', $value) === 1;
}
使用例です。
var_dump(isNonNegativeIntegerString("0")); // true
var_dump(isNonNegativeIntegerString("123")); // true
var_dump(isNonNegativeIntegerString("00123")); // false
var_dump(isNonNegativeIntegerString("-1")); // false
整数に変換して取得する関数
整数として妥当なら int、不正なら null を返す関数にしておくと便利です。
function toIntOrNull(string $value): ?int
{
$int = filter_var($value, FILTER_VALIDATE_INT);
return $int === false ? null : $int;
}
使用例です。
$value = $_GET['value'] ?? '';
$int = toIntOrNull($value);
if ($int === null) {
exit('整数ではありません');
}
1以上の整数に限定して取得する関数
function toPositiveIntOrNull(string $value): ?int
{
$int = filter_var($value, FILTER_VALIDATE_INT, [
'options' => [
'min_range' => 1,
],
]);
return $int === false ? null : $int;
}
使用例です。
$id = toPositiveIntOrNull($_GET['id'] ?? '');
if ($id === null) {
http_response_code(400);
exit('Invalid ID');
}
ただし、この関数では "+123" や " 123 " も通る点には注意してください。
Laravelなどのフレームワークを使う場合
バリデーション機能を使うのが基本
Laravelなどのフレームワークでは、PHPの関数を直接使うより、バリデーション機能を使うことが多いです。
Laravelであれば、たとえば次のように書けます。
$request->validate([
'id' => ['required', 'integer', 'min:1'],
]);
このように書けば、id が必須で、整数で、1以上であることを検証できます。
厳密な表記ルールが必要なら正規表現も使う
ただし、フレームワークの integer ルールがどのような表記を許可するかは、仕様によって異なります。
たとえば、次のようなルールを厳密に決めたい場合があります。
先頭ゼロを禁止したい
プラス記号を禁止したい
空白を禁止したい
半角数字だけにしたい
このような場合は、integer だけでなく、正規表現によるルールを追加すると安心です。
$request->validate([
'id' => ['required', 'regex:/^[1-9][0-9]*$/'],
]);
目的別のおすすめ一覧
半角数字だけを判定したい
ctype_digit($value)
向いている値です。
"123"
"00123"
"0"
1以上の整数IDを判定したい
preg_match('/^[1-9][0-9]*$/', $value)
向いている値です。
"1"
"123"
拒否される値です。
"0"
"00123"
"-1"
"+1"
" 1 "
0以上の整数を判定したい
preg_match('/^(0|[1-9][0-9]*)$/', $value)
向いている値です。
"0"
"1"
"123"
拒否される値です。
"00"
"001"
"-1"
"+1"
負の整数も許可したい
filter_var($value, FILTER_VALIDATE_INT)
または、表記ルールを厳密にするなら次のようにします。
preg_match('/^-?(0|[1-9][0-9]*)$/', $value)
範囲指定もしたい
filter_var($value, FILTER_VALIDATE_INT, [
'options' => [
'min_range' => 1,
'max_range' => 100,
],
]);
小数や指数表記も含めて数値判定したい
is_numeric($value)
ただし、整数判定には向いていません。
まとめ
PHPで文字列の中の整数を判定する場合、最も大切なのは 何を整数として許可するのかを先に決めること です。
単に「整数」といっても、次のように仕様が分かれます。
"00123" を許可するのか
"+123" を許可するのか
"-123" を許可するのか
" 123 " を許可するのか
"0" を許可するのか
半角数字だけを見たいなら、ctype_digit() がシンプルです。
ctype_digit($value)
PHPの整数として妥当か確認し、範囲指定もしたいなら、filter_var() が便利です。
filter_var($value, FILTER_VALIDATE_INT)
先頭ゼロ禁止、符号禁止、空白禁止など、表記ルールを厳密に決めたいなら、正規表現が最も明確です。
preg_match('/^[1-9][0-9]*$/', $value)
一方で、is_int()、is_numeric()、(int)、intval() は使いどころに注意が必要です。
is_int("123"); // false
is_numeric("1e3"); // true
(int) "123abc"; // int(123)
intval("12.9"); // int(12)
実務では、次の順番で処理すると安全です。
1. 入力値を受け取る
2. 仕様に合わせて検証する
3. 必要に応じて整数へ変換する
4. 範囲チェックを行う
特に、URLパラメータやフォーム入力を扱う場合は、いきなり (int) で変換するのではなく、先に検証する ことが重要です。
以上、PHPの文字列の中の整数の判定についてでした。
最後までお読みいただき、ありがとうございました。










