PHP Tips | 文字列処理:フォーマット – 数字のみ抽出

PHP PHP
スポンサーリンク

「数字のみ抽出」でやりたいことをまずイメージする

ここでやりたいのは、こういうことです。

"合計: 1,234円(税込)"   → "1234"
"TEL: 03-1234-5678"       → "0312345678"
"注文番号 #A-2024-001"    → "2024001"
"123ABCあいう"         → "123"

つまり、

文字列の中から「数字だけ」を取り出したい。
数字以外の文字は、全部いらない。

という処理です。

電話番号、郵便番号、金額、注文番号、会員番号など、
「数字を含む文字列」を扱う場面では、ほぼ毎回出てきます。

ここでは「初心者でも迷わない形」で、
数字だけを取り出すユーティリティを作っていきます。


基本の考え方:いらないものを全部「消す」

「抽出」と聞くと難しく感じるけれど…

「数字のみ抽出」と聞くと、
「数字を一個一個拾い集める」イメージを持つかもしれません。

でも、実装としては逆に考えた方がシンプルです。

「数字以外を全部消す」
=「結果として、数字だけが残る」

この発想に切り替えると、一気に楽になります。

preg_replace で「数字以外」を空文字にする

PHP で「条件に合わない文字を全部消す」定番は、preg_replace です。

/**
 * 数字以外の文字をすべて削除して、「数字だけの文字列」にする
 */
function onlyDigits(string $value): string
{
    return preg_replace('/[^0-9]/', '', $value);
}
PHP

ここでのポイントは、正規表現 /[^0-9]/ です。

  • [0-9] は「0〜9 のどれか1文字」
  • [^0-9] は「0〜9 以外の1文字」
  • それを ''(空文字)に置き換える → 「数字以外を全部消す」

という意味になります。

動きを例で確認する

echo onlyDigits("合計: 1,234円(税込)"); // 1234
echo onlyDigits("TEL: 03-1234-5678");     // 0312345678
echo onlyDigits("注文番号 #A-2024-001");  // 2024001
echo onlyDigits("abc");                   // (空文字)
PHP

「数字以外は全部いらない」という割り切りなので、
記号・文字・スペースなどはきれいさっぱり消えます。


日本語環境では「全角数字」に注意する

全角数字はそのままだと「数字扱いされない」

日本語入力だと、ユーザーが全角で数字を入れてくることがあります。

"12345"
"合計:12,345円"

さっきの onlyDigits() にそのまま渡すと、
全角数字は「0〜9 ではない」ので、全部消えてしまいます。

echo onlyDigits("12345"); // (空文字)
PHP

これでは困るので、

「全角数字を半角に変換してから、数字以外を消す」

という二段構えにします。

mb_convert_kana で全角数字 → 半角数字

/**
 * 全角数字も含めて、「数字だけの文字列」にする
 */
function onlyDigitsWithZenkaku(string $value): string
{
    // 全角数字を半角に変換
    $value = mb_convert_kana($value, 'n', 'UTF-8');

    // 数字以外を削除
    return preg_replace('/[^0-9]/', '', $value);
}
PHP

mb_convert_kana($value, 'n', 'UTF-8')'n' は「全角数字 → 半角数字」という指定です。

これで、次のように動きます。

echo onlyDigitsWithZenkaku("12345");             // 12345
echo onlyDigitsWithZenkaku("合計:12,345円");  // 12345
echo onlyDigitsWithZenkaku("TEL:03−1234−5678"); // 0312345678
PHP

日本語環境の業務システムなら、
「全角数字を半角にしてから数字以外を消す」は、ほぼ必須パターンです。


「数字だけの文字列」から「数値」に変換する

いきなり (int) キャストするのは危険

よくある失敗パターンがこれです。

$raw    = "¥12,345円";
$amount = (int)$raw;

var_dump($amount); // int(0)
PHP

(int) キャストは、先頭から見て「数字じゃない」と判断した時点で 0 にしてしまうので、
通貨記号や文字が付いていると、ほぼ 0 になります。

だからこそ、

  1. まず「数字だけの文字列」にする
  2. そのあとで「数値」にキャストする

という順番が大事です。

正しい流れの例

$raw     = "¥12,345円";
$digits  = onlyDigitsWithZenkaku($raw); // "12345"
$amount  = (int)$digits;                // 12345

var_dump($amount); // int(12345)
PHP

この「一呼吸置く」だけで、
金額や数量の扱いが一気に安定します。


実務での使いどころのイメージ

フォーム入力の金額を正規化する

$raw     = $_POST['amount'] ?? '';
$digits  = onlyDigitsWithZenkaku($raw); // "12345" など
$amount  = (int)$digits;                // 12345

// $amount を DB に保存する
PHP

保存は「数値」または「数字だけの文字列」にしておき、
表示するときに number_format や通貨記号付きフォーマットを使う、
という設計にすると、金額周りのバグがかなり減ります。

電話番号・郵便番号の前処理として使う

電話番号や郵便番号のフォーマット処理も、
最初のステップは「数字だけにする」でした。

function normalizePhoneDigits(string $phone): string
{
    return onlyDigitsWithZenkaku($phone);
}

function normalizeZipDigits(string $zip): string
{
    return onlyDigitsWithZenkaku($zip);
}
PHP

こうしておけば、
後続の処理は「数字だけの文字列」を前提に書けるので、
ロジックがシンプルになります。


設計として一番大事なポイント

「入力のゆらぎ」を一箇所で吸収する

ユーザー入力や外部システムからのデータは、必ず「ゆらぎ」があります。

  • カンマ付きだったり、なかったり
  • 全角だったり、半角だったり
  • 単位や記号が付いていたり

これを、アプリケーションのあちこちで個別に対処し始めると、
すぐにコードが壊れやすくなります。

そこで、

「数字を扱う前に、必ず onlyDigitsWithZenkaku() を通す」

というルールを決めてしまうと、
「入力のゆらぎ」を一箇所で吸収できるようになります。

結果として、

  • DB の中身がきれいにそろう
  • バリデーションが書きやすくなる
  • バグの原因が減る

という、かなり大きな効果が出てきます。


まとめ:今日からの「数字のみ抽出」ユーティリティ

押さえておきたいのは、この3つです。

// 純粋に「数字以外を消す」版
function onlyDigits(string $value): string
{
    return preg_replace('/[^0-9]/', '', $value);
}

// 全角数字も考慮した実務向け版
function onlyDigitsWithZenkaku(string $value): string
{
    $value = mb_convert_kana($value, 'n', 'UTF-8');
    return preg_replace('/[^0-9]/', '', $value);
}

// 「数字だけ」→「数値」にするまで含めたヘルパー
function toIntFromMixedNumber(string $value): int
{
    $digits = onlyDigitsWithZenkaku($value);
    return $digits === '' ? 0 : (int)$digits;
}
PHP

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