PHP Tips | 文字列処理:入力補助 - 数値文字列判定

PHP PHP
スポンサーリンク

何をしたいユーティリティなのか

「数値文字列判定」は、 「この文字列、ちゃんと“数値として扱っていいやつ”か?」をチェックするためのユーティリティです。

フォーム入力、クエリパラメータ、JSON の値など、 一見数字っぽいけど、実は変な文字が混ざっていることがあります。

"123" は OK。 " 123 " はどうする? "00123" は? "12.5" は? "123"(全角)は?

ここを自分でルール決めして、コードに落とし込むのが「数値文字列判定」です。

PHP の is_numeric のクセを知る

is_numeric は「ゆるめの判定」

PHP には is_numeric があります。

var_dump(is_numeric('123'));     // true
var_dump(is_numeric('12.5'));    // true
var_dump(is_numeric('+10'));     // true
var_dump(is_numeric('1e3'));     // true (指数表記)
var_dump(is_numeric('0123'));    // true
var_dump(is_numeric('123'));  // true(全角数字も true)
PHP

「数値として解釈できるか」を見ているので、 指数表記や全角数字も OK になります。

業務で「ID としての整数だけを許したい」場合には、 このゆるさが逆に困ることがあります。

「整数だけ」を判定するユーティリティ

正規表現で「0〜9 だけ」を許す

「整数だけ」「マイナスも含めるかどうか」など、 ルールをはっきり決めてしまうのが一番分かりやすいです。

例えば、「0〜9 の数字だけ」「先頭に任意でマイナスを許す」というルールなら、こう書けます。

/**
 * 「整数として扱ってよい文字列か」を判定する
 *
 * ルール:
 * - 先頭に任意で '-' を許可
 * - それ以外は 0〜9 の数字だけ
 * - 空文字は false
 */
function is_int_string(string $value): bool
{
    // 前後の空白は許さないなら trim しない
    // 許したいならここで trim する
    if ($value === '') {
        return false;
    }

    return (bool)preg_match('/^-?[0-9]+$/', $value);
}
PHP

この関数の重要ポイントは、「自分でルールを決めている」ことです。

^-?[0-9]+$ という正規表現は、

  • ^ … 文字列の先頭
  • -? … マイナス記号が 0 回または 1 回
  • [0-9]+ … 数字が 1 回以上
  • $ … 文字列の末尾

という意味になります。

例題で挙動を確認する

OK になるもの

var_dump(is_int_string('0'));      // true
var_dump(is_int_string('123'));    // true
var_dump(is_int_string('-10'));    // true
PHP

「純粋な整数」として扱いたいものは、ちゃんと true になります。

NG にしたいもの

var_dump(is_int_string(''));       // false
var_dump(is_int_string(' 123'));   // false(先頭に空白)
var_dump(is_int_string('12.5'));   // false(小数点)
var_dump(is_int_string('+10'));    // false(プラス記号)
var_dump(is_int_string('1e3'));    // false(指数表記)
var_dump(is_int_string('123')); // false(全角数字)
PHP

「ID としてはおかしいよね」というものは、全部 false になります。 ここが is_numeric との大きな違いです。

「前後の空白は許す」版も作っておく

trim を入れるかどうかは設計の話

ユーザー入力だと、うっかり前後に空白が入ることがあります。

" 123 "

これを「許すかどうか」は設計次第ですが、 許したいなら trim を入れた別関数を用意しておくと分かりやすいです。

function is_int_string_trimmed(string $value): bool
{
    $value = trim($value);

    if ($value === '') {
        return false;
    }

    return (bool)preg_match('/^-?[0-9]+$/', $value);
}
PHP

こうしておけば、

  • DB の ID チェックには「trim なし版」
  • フォーム入力のチェックには「trim あり版」

といった使い分けができます。

「数値として扱えるか」をざっくり見たいときのユーティリティ

is_numeric をラップしておく

「整数だけじゃなく、小数も指数表記も許したい。とにかく数値なら OK」という場面もあります。 その場合は、is_numeric をそのまま使いつつ、前後の空白だけ整えておくと扱いやすいです。

/**
 * 「数値として解釈できる文字列か」を判定する(ゆるめ)
 *
 * - 前後の空白は無視
 * - is_numeric にそのまま渡す
 */
function is_numeric_string(string $value): bool
{
    $value = trim($value);

    if ($value === '') {
        return false;
    }

    return is_numeric($value);
}
PHP

例:

var_dump(is_numeric_string('12.5'));    // true
var_dump(is_numeric_string('1e3'));     // true
var_dump(is_numeric_string('  10  '));  // true
var_dump(is_numeric_string('abc'));     // false
PHP

「型安全な整数判定」とは別に、「ざっくり数値かどうか」を見るユーティリティもあると便利です。

実務での使いどころ

ID や数量のバリデーション

フォームで「ユーザー ID」「数量」「ページ番号」などを受け取るとき、 is_int_string でチェックしてから intval する、という流れが定番になります。

$rawId = $_GET['id'] ?? '';

if (!is_int_string($rawId)) {
    // 不正な ID として扱う
    throw new InvalidArgumentException('id must be integer string');
}

$id = (int)$rawId;
PHP

「文字列のままだけど、整数として扱っていいか」を先に判定しておくことで、 変な値が入り込むのを防げます。

JSON や設定ファイルの値チェック

JSON や設定ファイルから読み込んだ値が「本当に数値か」を確認したいときも同じです。

$config = decode_json_to_array($json);

if (!array_key_exists('max_users', $config) || !is_int_string((string)$config['max_users'])) {
    throw new RuntimeException('config.max_users must be integer string');
}

$maxUsers = (int)$config['max_users'];
PHP

「型のズレ」を早めに検知しておくことで、 後の処理でのバグを減らせます。

まとめ:今日からの「数値文字列判定」ユーティリティ

数値文字列判定の本質は、「自分が“数値として扱いたいルール”をコードに落とす」ことです。

整数だけを許したいなら、preg_match('/^-?[0-9]+$/') のような正規表現で厳しく見る。 前後の空白を許すかどうかは、trim を入れるかどうかで分ける。 小数や指数表記も含めてざっくり数値を許したいなら、is_numeric をラップする。

まずは、この 1 本をプロジェクトに置いておくと良いです。

function is_int_string(string $value): bool
{
    if ($value === '') {
        return false;
    }

    return (bool)preg_match('/^-?[0-9]+$/', $value);
}
PHP

そして、「ここは ID だから絶対整数」「ここは数量だから整数」「ここは金額だから小数もあり」 といったルールごとに、どの判定関数を使うかを決めていく。 それだけで、入力まわりの「変な値」に悩まされることが、かなり減ります。

タイトルとURLをコピーしました