1. 導入
Web開発において、外部から送られてくるデータ(フォーム入力、APIリクエスト、外部CSVなど)には、予期せぬ文字化けや、エンコーディング仕様に合致しない「不正なバイトシーケンス」が含まれることがあります。これらをそのままデータベースへ保存したり、処理しようとすると、例外が発生したり、システムが予期せぬ動作をしたりするリスクがあります。PHP 7.2で導入されたmb_scrub関数は、そうした「不正なバイト」を安全な代替文字(置換文字)に置き換えることで、プログラムの堅牢性を高める非常に便利なツールです。
2. 基礎知識
マルチバイト文字列(UTF-8など)では、特定のバイトパターンが文字として定義されています。しかし、通信途中のデータ欠損や不正なエンコード処理により、定義外のバイト列が混入することがあります。
これまで、こうした不正なバイト列を取り除くには、一度別のエンコーディングに変換してから戻すといった「ハック」が必要でした。mb_scrubは、「自分自身のエンコーディングで再変換する」という処理を行うことで、不正な箇所だけを検出して置換する専用の関数です。
3. 実装/解決策
mb_scrubは非常にシンプルで、対象の文字列とエンコーディングを指定するだけです。
基本的には対象文字列を第一引数に渡すだけで、現在の内部エンコーディング設定に基づいて処理が行われます。もし明示的にUTF-8として処理したい場合は、第二引数にエンコーディングを指定してください。不正なバイト列は見つかった場合、PHPの標準的な置換文字(通常は「?」)に置き換えられます。
4. サンプルプログラム
以下は、不正なバイトシーケンスを含む可能性のある文字列をクリーンアップする実用的なコード例です。
/
function sanitizeInput(string $input): string
{
// UTF-8として不正なバイト列を置換する
// mb_scrubは指定されたエンコーディングで再エンコードすることで
// 不正なバイト列を検出し、自動的に置換文字に置き換えます
$cleaned = mb_scrub($input, ‘UTF-8’);
return $cleaned;
}
// サンプル: 途中で途切れたUTF-8文字(不正なバイト)を含む文字列
// ※以下の文字列は便宜上の例です
$dirtyString = “正常な文字列” . “\xFF” . “あいうえお”;
$result = sanitizeInput($dirtyString);
echo “元データ: ” . bin2hex($dirtyString) . PHP_EOL;
echo “浄化後: ” . $result . PHP_EOL;
// 浄化後は \xFF の部分が置換文字に置き換わります
?>
5. 応用・注意点
実務における注意点は以下の通りです。
・パフォーマンスへの考慮:
大量の文字列をループ内で処理する場合、mb_scrubの呼び出しはオーバーヘッドになります。必要な箇所(外部からの入力直後など)でのみ実行するようにしましょう。
・文字化けの根本解決ではない:
mb_scrubは「不正なバイトを消す(置換する)」ものであり、文字コードの誤変換(Shift-JISをUTF-8と誤認識しているなど)を直すものではありません。文字コードの判定にはmb_detect_encodingなどを併用してください。
・置換文字の確認:
環境や設定によっては置換文字が期待と異なる場合があります。出力先がHTMLであれば、適切にHTMLエンティティ化されているかどうかも併せて確認することが、セキュリティ上のベストプラクティスです。