mb_strimwidthで文字列をきれいに丸める
mb_strimwidth とは、文字数ではなく表示幅で文字列を丸め、必要なら末尾に省略記号を付けてくれる関数です。全角を2、半角を1として数えます。
文字数ではなく表示幅で切る
一覧画面で長いタイトルを「…」で省略したいとき、mb_substr で文字数を切るとレイアウトが崩れることがあります。全角と半角が混ざると1文字の見た目の幅が違うからですね。mb_strimwidth は文字数ではなく「表示幅」で丸めてくれるので、こういう用途にぴったりです。全角を2、半角を1として数えます。
$title = 'PHPで学ぶ設計入門';
echo mb_strimwidth($title, 0, 10);
// 幅10で切り詰められる(全角=2で計算)
末尾に省略記号を付ける
第4引数に「切り詰めたときに付ける文字列」を渡せます。ここに「…」や「…」を指定すると、はみ出したときだけ末尾に付いてくれます。しかも指定した幅の中に省略記号の幅も含めて調整してくれるので、自分で長さ計算をしなくて済むのがありがたいところです。
$text = 'これは長めのタイトルサンプルです';
echo mb_strimwidth($text, 0, 16, '...');
// 幅16に収まるように切って末尾に ... が付く
// (... の幅も込みで16に収まる)
// 短い文字列はそのまま(省略記号は付かない)
echo mb_strimwidth('短い', 0, 16, '...');
// "短い"
元の文字列が指定幅より短ければ省略記号は付かないので、条件分岐を書かずに済むのが気持ち良いですね。
全角半角混在での挙動と注意点
混在文字列でも幅ベースで正しく切れるのがこの関数の真価です。ただし、幅の途中に全角文字がかかると、その全角文字は含めずに切るので、指定幅ぴったりにならないことがあります。1幅だけ空くケースがあるという理解でいると、テーブル整形などで慌てずに済むと思います。第2引数は開始「幅」であって文字位置ではない点も、地味に間違えやすいところです。
$mix = 'ABあいうEF';
echo mb_strimwidth($mix, 0, 5);
// "ABあ" 全角が幅にかかる手前で切れる
// 第3引数はエンコーディングではなく trimmarker の後、
// エンコーディング指定は最後に渡す
echo mb_strimwidth($mix, 0, 5, '', 'UTF-8');
まとめ
mb_strimwidth は「見た目の幅で丸めて省略記号まで付ける」処理を一発でこなしてくれる、一覧表示の強い味方です。文字数ではなく表示幅で数えること、全角がかかると幅ぴったりにならないこと、この2点を理解しておけば、日本語混じりのタイトル省略で崩れないUIが作れると思います。
よくある質問
Q. mb_substr と何が違いますか?
A. mb_substr は文字数で切るので、全角と半角が混ざると見た目の幅が揃いません。mb_strimwidth は表示幅で切るので、一覧のレイアウトが崩れにくいです。
Q. 省略記号はどう付けますか?
A. 第4引数に '...' などを渡すと、はみ出したときだけ末尾に付きます。省略記号の幅も込みで指定幅に収めてくれます。
Q. 短い文字列にも記号が付きますか?
A. 付きません。元の文字列が指定幅より短ければそのまま返るので、条件分岐を自分で書かずに済みます。