フォームのバリデーションにおいて文字列の長さの上限、下限を定めるルールは定番です。今回は文字列の長さをどうやって測るかという話をします。
文字列の長さをどう測るかなんてわかりきったことじゃないのかと思われるかもしれません。人間が測るぶんには見たまんま文字を数えていけばいいので簡単ですが、コンピューター上では文字はデジタルで表現され、何らかのコードの形で存在します。そして文字列をコード化する標準は複数存在します。
たとえば WordPress のデフォルトは UTF-8 です。これは文字を可変長符号として扱う方式なので1文字が何オクテットで符号化されるかはその文字によって異なります。例えば ASCII に含まれる範囲の英数字なら1文字が1オクテットで表現されますが、日本語の仮名や漢字の1文字なら3オクテット必要です。
一方、JavaScript は文字列を UTF-16 で符号化します。UTF-16 は1文字を16ビット (2オクテット) の固定長符号で表現します。コンピューターは文字列をグリフではなくコードの集合と認識しているので、コードの個数を基準に文字列の長さを測るのが自然です。その観点から言えば、固定長符号化方式を採る UTF-16 のほうが文字列の長さを測るのには有利でしょう。
ブラウザ上でのフロントエンドバリデーションの基盤として動いているのは JavaScript なので、HTML の maxlength 属性と minlength 属性のバリデーションは入力文字列を UTF-16 コード単位として数えます。
Schema-Woven Validation にも maxlength と minlength のルールタイプが用意されており、HTML の同名の属性に準拠したバリデーションを適用します。すなわち、UTF-16 コード単位を基準として算出した文字列長と threshold プロパティ値を比較します。
その際、JavaScript ではもともと文字列が UTF-16 で表現されるため、そのまま String オブジェクトの length プロパティをチェックすればいいだけなので簡単ですが、PHP 版の SWV においては一旦 UTF-8 文字列を UTF-16 に変換する必要が生じます。もちろんそのあたりは SWV 側でよしなに処理しますので気にしなくて結構ですが。
あと最後に小ネタですが、UTF-16 では1文字を16ビットの1コード単位で表現すると書きましたが物事には必ず例外があり、ごく一部の文字については2コード単位で表現されます。絵文字なんかがそれに当たります。では問題です。次の文字列の長さは UTF-16 コード単位でいくつでしょうか?
ぴえん🥺
Leave a comment