PHPは中英混合文字列の長さを取得する方法


今晩は枠のフォームを書いてクラスを検証する時、ある文字列の長さが指定区間内にあるかどうかを判断する必要があります。自然にPHPの中のstreen関数を思い出しました。

$str = 'Hello world!';
echo strlen($str); // 12
ですが、PHPが持っている関数の中で、streenとmb_strelenは、文字列のバイト数を計算することによって長さを計算し、異なる符号化の場合、中国語のバイト数は異なる。GBK/GB 2312では、中国語の文字は2バイトを占めていますが、UTF-8では中国語の文字は3バイトを占めています。

$str = ' , !';
echo strlen($str); // GBK GB2312 12,UTF-8 18
で、文字列の長さを判断する時、文字列のバイト数ではなく文字列の数を判断する必要があります。例えば、UTF-8の下のこのPHPコード:

$name = ' ';
$len = strlen($name);
// FALSE, UTF-8 9
if($len >= 3 && $len <= 8){
 echo 'TRUE';
}else{
 echo 'FALSE';
}
では、中国語文字列を含む長さが得られますか?正則で中国語の文字の個数を計算できます。GBK/GB 2312符号化で2で割って、UTF-8符号化で3で割って、最後に非中国語文字列の長さを加えますが、これはちょっと面倒くさいです。
WordPressのこのようなコードは、以下の通りです。

$str = 'Hello, !';
preg_match_all('/./us', $str, $match);
echo count($match[0]); // 9
思想は、正規表現で文字列を単一文字に分割し、countで直接にマッチする文字数を計算することです。
しかし、以上のコードはUTF-8符号化ではGBK/GB 2312の中国語文字列を処理できません。GBK/GB 2312の中国語文字は2文字と認識されて計算された中国語文字の数が倍になります。そこで、GBK/GB 2312及びUTF-8のコードに対応できる方法を思い付きました。大牛の指導を待っています。
このような本来の意味は、フレームが複数の符号化フォーマットに対応できるようにするためであるが、通常は日常的に開発されているプロジェクトの一つは、なぜ符号化されたのかを決定することができるので、以下の関数を使用して文字列の長さを簡単に取得することができる:

$tmp = @iconv('gbk', 'utf-8', $str);
if(!empty($tmp)){
 $str = $tmp;
}
preg_match_all('/./us', $str, $match);
echo count($match[0]);