PHP でフォームデータを漢字入力チェックする方法

はじめに

実務にて、フォームデータを漢字入力チェックするバリデーション(入力値の検証)を実装する作業があり、それを解決した情報になります。Web 開発の初心者、初学者の方にもわかりやすいように、ソースコードを編集してサンプルを公開しています、ご参考になれば幸いです。

検証環境

サンプル

解説

サンプルのソースコードを基に、基本的な PCRE 正規表現構文 を用いて説明します。

漢字のチェック

漢字の Unicode には、たくさんの ブロック が定義されています。

CJK 統合漢字CJK 拡張漢字 A ~ G、CJK 互換漢字CJK 互換漢字補助 などです。

よく見る [一-龠] は、CJK 統合漢字(4E00) から (9FA0) までの一部です。地名や人名漢字を含む CJK 統合漢字拡張 A や旧漢字を含む CJK 互換漢字 などの文字にマッチしないので、理解しないでコピペをしている場合は、使い所に気を付けましょう。

全ての漢字を正規表現で網羅するのは現実的ではありません、前述したブロックと一部の漢字を含めて、下記のように preg_match でチェックします。

function checkKanji(string $str): int|false {
  return preg_match("/\A[々〇〻\x{3400}-\x{9FFC}\x{F900}-\x{FAD9}\x{20000}-\x{3134A}]+\z/u", $str);
}

ブロック毎に指定する場合は、下記のように記述します。

function checkKanji2(string $str): int|false {
  return preg_match("/\A[々〇〻\x{3400}-\x{4DBF}\x{4E00}-\x{9FFC}\x{F900}-\x{FAD9}\x{20000}-\x{2A6DD}\x{2A700}-\x{2B734}\x{2B740}-\x{2B81D}\x{2B820}-\x{2CEA1}\x{2CEB0}-\x{2EBE0}x{2F800}-\x{2FA1F}\x{30000}-\x{3134A}]+\z/u", $str);
}

下記の PCRE 正規表現構文を記述しています。

下記の文字列とマッチします。

々〇〻㐀䶿一鿼豈龎𠀀𪛝𪜀𫜴𫝀𫠝𫠠𬺡𬺰𮯠丽𪘀𰀀𱍊

実は、もっと簡単なやり方があります。

Unicode 文字プロパティ の \p{Han} で、下記のようにチェックする方法です。

function checkKanji3(string $str): int|false {
  return preg_match("/\A\p{Han}+\z/u", $str);
}

\p{Han} の文字範囲は下記になります。

  • ⺀-⺙ : Unicode 2000-2FFF(2E80) から (2E99) まで
  • ⺛-⻳ : Unicode 2000-2FFF(2E9B) から (2EF3) まで
  • ⼀-⿕ : Unicode 2000-2FFF(2F00) から (2FD5) まで
  • : Unicode 3000-3FFF(3005)
  • : Unicode 3000-3FFF(3007)
  • 〡-〩 : Unicode 3000-3FFF(3021) から (3029) まで
  • 〸-〻 : Unicode 3000-3FFF(3038) から (303B) まで
  • 㐀-䶿 : CJK 統合漢字拡張 A
  • 一-鿼 : CJK 統合漢字
  • 豈-舘 : Unicode F000-FFFF(F900) から (FA6D) まで
  • 並-龎 : Unicode F000-FFFF(FA70) から (FAD9) まで
  • 𠀀-𪛝 : CJK 統合漢字拡張 B
  • 𪜀-𫜴 : CJK 統合漢字拡張 C
  • 𫝀-𫠝 : CJK 統合漢字拡張 D
  • 𫠠-𬺡 : CJK 統合漢字拡張 E
  • 𬺰-𮯠 : CJK 統合漢字拡張 F
  • 丽-𪘀 : CJK 互換漢字補助
  • 𰀀-𱍊 : CJK 統合漢字拡張 G

下記の文字列とマッチします。

⺀⺙⺛⻳⼀⿕々〇〡〩〸〻㐀䶿一鿼豈舘並龎𖿰𖿱𠀀𪛝𪜀𫜴𫝀𫠝𫠠𬺡𬺰𮯠丽𪘀𰀀𱍊

また、^[...]$ という書き方は 修飾子 の m を指定している場合に、改行の有無によって下記のように動作が変わります。

$str = '々〇
〻';

var_dump(preg_match("/\A[々〇〻]+\z/u", $str)); // マッチしない int(0)
var_dump(preg_match("/\A[々〇〻]+\z/mu", $str)); // マッチしない int(0)
var_dump(preg_match("/^[々〇〻]+$/u", $str)); // マッチしない int(0)
var_dump(preg_match("/^[々〇〻]+$/mu", $str)); // マッチする int(1)

動作が統一されている /\A[...]\z を指定するのが無難かと思います。

まとめ

基本的に /\A\p{Han}+\z/u でチェックして、絞り込みが必要な場合は、Unicode 一覧表 を確認しながら正規表現を書き換えて柔軟に対応すれば良いと思います。

以上です。

おわりに

サンプルのソースコードを再利用する際は、関わっている案件で用いられる文字セットの範囲を調査してからご利用ください。