前回はバリデーションの前処理として両端の空白文字を取り除くことについてお話ししましたが、この処理に使うのが trim() です。今回は、おなじみ trim() に関するあまりなじみのなさそうな話をしたいと思います。
trim() といえば PHP の関数としてご存じの方が多いかと思いますが、同名の関数が JavaScript にも存在します。こちらは正確にいえば String プロトタイプの trim() メソッド (String.prototype.trim()) ですが。どちらの trim() も文字列の両端から空白文字を取り除くことが用途です。あまり深く考えずに同等の関数と捉えている方が多いんじゃないかと思いますが、実際には PHP の trim() と JavaScript の trim() はまるっきり違います。
PHP の trim() はデフォルトでスペース、タブ、LF、CR、NUL、垂直タブの6種類の ASCII 文字を削除します。他方、JavaScript の trim() はそれらに加えて Unicode の多言語空白文字群も削除の対象に含みます。
日本語話者にわかりやすい例を挙げると U+3000 (IDEOGRAPHIC SPACE) があります。他の言語話者向けに説明すると、日本語入力モードでスペースバーを叩いたときに入力されるのがこの文字で、ASCII のスペース2個分の幅をとることから「全角スペース」と呼ばれます。話を戻すと、要するに、PHP の trim() は全角スペースを取り除かないが、JavaScript の trim() は取り除く、というわけです。
なお、PHP 8.4 から導入された多言語対応の mb_trim() というのもあるのですが、これがまたややこしい話で、Unicode の空白文字も削除対象となったのはいいのですが、JavaScript の trim() と比較してみると依然微妙な食い違いがあることがわかります。
mb_trim() の削除対象に含まれて JavaScript の trim() の対象に含まれない文字の例として U+180E (MONGOLIAN VOWEL SEPARATOR) がありますが、MDN の解説によるとこの文字は Unicode の更新にともなって Space_Separator カテゴリーから移動されたとのことです。このことから mb_trim() は古いバージョンの Unicode を基準に仕様が定められていると推測できます。
異なるプラットフォーム間でも一貫性のあるバリデーションを実現するのが Schema-Woven Validation の意義ですから、このように trim() がバラバラの挙動を示すのは困るわけです。そこで SWV では JavaScript の trim() の挙動に合わせることにし、PHP 向けには strip_whitespaces() というカスタム関数を trim() の代替として使うことで一貫性のある両端空白文字の削除を実現しています。
なお JavaScript の trim() と協調する PHP 関数を設けるアイデアについては WordPress の Trac に提案済みですのでいずれ WordPress でも普通に使えるようになるかもしれません。
Leave a comment