題の通りです。よく PHP の文字数を数える関数にはバイト数と文字数が一致する英語圏ではstrlen、マルチバイト文字がある日本ではmb_strlenが使われている印象です。
PHP: strlen – Manual
PHP: mb_strlen – Manual
grapheme_strlenはバイト数に関わらず、見た目の文字の数を数える関数です。次リンクの詳しい説明には書記素という聞きなれないであろう語が使われていますが、これは一文字を一文字であると認識できる図形単位のことです。要するに見た目の文字数の単位です。
grapheme_strlenを使うと次の様なことができます。
<?php
$str = '🏴';
$res = [
'strlen' => strlen($str),
'mb_strlen' => mb_strlen($str),
'grapheme_strlen' => grapheme_strlen($str),
];
echo json_encode($res, JSON_PRETTY_PRINT);
/*
{
"strlen": 28,// 28byte
"mb_strlen": 7,// mb_strlen はサロゲートペアや合字周りで期待と異なる挙動をします
"grapheme_strlen": 1// 期待通り
}
*/
Online PHP editor | output for Cduj5#上記コードのデモ
grapheme_strlenを用いることで「メールの文面において1行はn文字まで」の様な文字数に関する要望を容易にある程度、実現できます。ただこれでも完璧ではなく、見る側の環境において絵文字が期待した通りに表示されない場合があります。稀にあるのが複数の文字を一文字として表示する合字に対応しておらず、こちらの環境では1文字の見た目、むこうの環境では3文字の見た目となる、といった場合です。こうなるとまた別の解決策が必要になります。