エンジニアのブログです。

JavaScriptのString.lengthをPHPで実装する

Posted at

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;

参考

文字コードに関しては以下の記事が参考になります。


About me
Creative Commons License

This blog's source code is published on GitHub.