導入
Web開発において、クレジットカード番号や会員IDなどの「識別番号」を入力させる機会は少なくありません。ユーザーの入力ミスを即座に検知し、APIやデータベースに無駄なクエリを投げないようにすることは、UX向上とサーバー負荷軽減の両面で重要です。本稿では、多くの識別番号で採用されている「Luhn(ルーン)アルゴリズム」を用いた、効率的なバリデーション手法について解説します。
基礎知識
Luhnアルゴリズム(別名:MOD-10アルゴリズム)は、1954年にIBMの科学者によって開発されたチェックサム方式です。主にクレジットカード番号やIMEI番号などの誤り検出に使われます。
このアルゴリズムの最大の特徴は、「計算がシンプルで高速」かつ「単一の桁の入れ替わりや、隣接する桁の入れ替わりによる誤りを検出できる」点です。
ルールは「右から数えて偶数番目の数字を2倍し、その結果が2桁になったら各桁を足す(または9を引く)」という手順を繰り返し、合計値が10で割り切れるかを確認するというものです。
実装/解決策
実務では、まず入力値から数字以外の文字を排除し、文字列の長さを正規化する必要があります。また、計算処理をループで回す際、配列操作ではなく文字列操作で行うことでメモリ消費を抑えるのがポイントです。
サンプルプログラム
以下は、現場でそのまま利用可能なLuhnアルゴリズムのチェック関数です。
/
function isValidLuhn(string $number): bool {
// 1. 数字以外を除去(スペースやハイフン対策)
$number = preg_replace(‘/[^0-9]/’, ”, $number);
// 空文字や短すぎる番号は無効
if (strlen($number) < 2) {
return false;
}
$sum = 0;
$length = strlen($number);
// 2. 右から順に処理を行う
for ($i = 0; $i < $length; $i++) {
// 右から数えた位置を取得(0始まり)
$digit = (int)$number[$length - 1 - $i];
// 偶数番目(右から2, 4, 6...番目)の処理
if ($i % 2 === 1) {
$doubled = $digit 2;
// 2倍した値が10以上なら(10の位が1)、9を引くことで各桁の和を計算したことと同じになる
$sum += ($doubled >= 10) ? ($doubled – 9) : $doubled;
} else {
// 奇数番目(右から1, 3, 5…番目)はそのまま加算
$sum += $digit;
}
}
// 3. 合計が10の倍数であれば検証通過
return ($sum % 10 === 0);
}
// 使用例
$card = ‘4111-1111-1111-1111’;
if (isValidLuhn($card)) {
echo “有効な番号です。”;
} else {
echo “無効な番号です。”;
}
?>
応用・注意点
実務でこのアルゴリズムを導入する際は、以下の点に注意してください。
1. セキュリティの限界
Luhnアルゴリズムは「入力ミス」を検知するためのものであり、番号が「実在するか」や「有効期限内か」を保証するものではありません。決済処理を行う場合は、必ず決済代行会社のAPIを通す必要があります。
2. パフォーマンス
大量のデータをバッチ処理で検証する場合、正規表現のオーバーヘッドが気になることがあります。その場合は、事前に文字種チェックを行ってからループ処理に入るなどの最適化を検討してください。
3. 9を引くロジックの理解
サンプルコードにある「2倍して9を引く」処理は、数学的には「2倍した値の各桁の和」と等価です。実務コードでは、条件分岐で冗長に書くよりも、この数学的特性を利用して簡潔に書くのがスマートなPHPエンジニアの流儀です。