「数字のみ抽出」でやりたいことをまずイメージする
ここでやりたいのは、こういうことです。
"合計: 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);
}
PHPmb_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 になります。
だからこそ、
- まず「数字だけの文字列」にする
- そのあとで「数値」にキャストする
という順番が大事です。
正しい流れの例
$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