PHP において、長音(ー)はひらがなかカタカナか?
結論から言ってしまうと、長音(ー)は
PHP 8.2 まではひらがなでもカタカナでもなく、
PHP 8.2 以降はひらがなでもあり、カタカナでもあります。
かな判定の不具合
文字列がひらがな・カタカナだけで構成されているかどうかをチェックする、以下のような PHP プログラムがあったのですが、ちょいちょい判定に失敗するという不具合が発生していました。
function check_kana(string $target)
{
return preg_match('/^[\p{Hiragana}\p{Katakana}]*$/u', $target);
}
失敗する文字列の共通点を確認すると長音(ー)が含まれているとダメみたいなのですが、新しい PHP のバージョンでは問題なく判定できているようです。
ひらがな・カタカナの扱いの変更
\p{Hiragana}、\p{Katakana} の仕様を調べたところ、 PHP のバージョンによって扱いが異なることがわかりました。
以前のバージョンでは、長音記号(U+30FC)は「Katakana」というスクリプト(文字体系)ではなく、複数のスクリプトで共通して使われる「Common」というカテゴリに分類されていました。
Unicode 14.0 において、特定のスクリプトで頻繁に使われる記号のプロパティが変更されました。これにより、長音記号(ー)が「Hiragana」「Katakana」スクリプトの一部として正式に認識されるようになったため、 PHP 8.1 以降の正規表現でもこれらにマッチするようになりました。
PHP では、PHP 8.2.0 のリリースノートに、以下のような記述があり、 ここで Unicode 14.0 が採用されました。
Updated bundled libpcre to 10.40.
(※PHP 8.1.0 時点では PCRE2 10.37 / Unicode 13.0 だったため、まだ長音はマッチしません)
表にまとめると、長音のマッチ状況は以下のようになります。
| PHPバージョン | PCRE2 | Unicode | \p{Hiragana} | \p{Katakana} |
|---|---|---|---|---|
| PHP 8.1 以前 | 10.39以下 | 13.0以前 | マッチしない | マッチしない |
| PHP 8.2 以降 | 10.40 | 14.0 | マッチする | マッチする |
バージョンに依存しない書き方
PHP 8.1 以前でも 8.2 以降でも、確実に長音を含めてバリデーションしたい場合は、依然として明示的に長音を文字クラスに加えるのが安全です。
さきのプログラムは以下のように、長音を含める形に変更しました。
function check_kana(string $target)
{
return preg_match('/^[\p{Hiragana}\p{Katakana}ー]*$/u', $target);
}
まとめ
PHP 8.2 からの挙動変更は、一見すると「不具合が勝手に直った」ようにも見えますが、実際には Unicode の仕様進化に伴う標準的な変更 でした。
今回のポイントを整理すると以下の通りです。
- PHP 8.2 以降: \p{Hiragana} や \p{Katakana} だけで長音(ー)もカバーできる。
- PHP 8.1 以前: 長音(ー)は Common カテゴリなので、明示的な指定が必要。
- ベストプラクティス: 実行環境のバージョンに関わらず、「長音を許容したいなら明示的に ー を含める」 書き方が最も安全で意図が明確。
「正規表現は一度書いたら一生モノ」と思いがちですが、OS や言語のアップデートによって、今回のように「文字の分類(プロパティ)」そのものが変わることもあるということで、たいへん勉強になりました。