JavaScriptのString.lengthをPHPで実装する
JavaScriptのString.lengthは、PHPでは以下のように実装します。
strlen(mb_convert_encoding($string, 'UTF-16')) / 2;
なぜPHPで実装が必要か
例えば、WEBアプリケーションでの文字カウント方式を、JavaScript側とバックエンド側(PHP)で統一したいときに必要です。
JavaScriptでは文字列をUTF-16で扱いますが、PHPを含めた他のプログラミング言語ではUTF-8で扱うことが主流です。そのため文字数のカウント方法が基本的に異なります。きちんと文字数カウントが統一されていないと、バリデーション時の文字数カウントにおいて、UI側とサーバー側で不整合が起きる可能性があります。
PHPは.ini
ファイルのdefault_charset
で符号化方式を指定できますが、実行環境依存になるため、なるべくコード側で制御するべきです。
JavaScriptのString.lengthの仕様
先も述べましたが、JavaScriptのString.length
とPHPのmb_strlen
などではカウント方法が異なります。
String.length - JavaScript | MDN には以下のように記載されています。。
このプロパティは、文字列内のコード単位の数を返します。UTF-16(JavaScript によって使われるフォーマット)は、基本的な文字を表すためには 1 つの 16 ビットを使用しますが、一般的に使用されない文字を表すために 2 つの 16 ビットを使用する場合があるので、実際の文字数と一致していない可能性があります。
一見複雑そうに見えますが、要はJavaScriptでは16ビットを1文字としてカウントしているだけです。そのため、UTF-16におけるサロゲートペアや結合文字を1文字としてカウントせず、2文字以上の値として返します。
'a'.length // 1
'あ'.length // 1
'😁'.length // 2 (サロゲートペア)
'👨👩👧👦'.length // 11 (結合文字)
PHPでの実装方法
上記の仕様を踏まえると、まずPHP上で文字列をUTF-16に変換し、そのバイト数を2で割ると実装できます。
strlen(mb_convert_encoding($string, 'UTF-16')) / 2;
参考
文字コードに関しては以下の記事が参考になります。
This blog's source code is published on GitHub.