PHPのmb_strimwidthが意図通り動かない問題

2017-03-02

#PHP 文字列

PHPの mb_strimwidth() は文字列を指定した幅に丸めることが出来る便利な関数ですが、この関数に固有の特殊な点がいくつかあり、意図通りに動作しないことも多いかと思います。それらの点について解説します。

mb_strimwidth の引数

mb_strimwidth の「幅」とは

PHPのマルチバイト文字列関数(mb_*)の多くは文字列をバイトではなく文字単位で扱い、まさにそれがこの関数群を利用するメリットなわけですが、mb_strimwidth()mb_strwidth() は文字列の「幅」を扱うようになっています。

これらの関数が扱う「幅」とは、文字数やピクセル数のことではありません。半角文字の幅を 1、全角文字の幅を 2として計算した、画面に表示される際のおおよその推定幅を意味します。
実際の表示においては文字列のピクセル幅はフォント等に依存しますので、きっちり同じ幅にはなりませんが、ある程度揃えば良い場合には便利な単位です。

第2引数 $start の注意点

$start で指定するのは、丸めの開始位置ではなく切り出し始めの位置です。従って、文字列の先頭を切る必要がなく、末尾だけを丸めたい場合は 0 と指定します。

また、単位が「幅」ではなく「文字数」である点にも注意が必要です。続く第3引数は幅で指定しますから余計に解りにくくなっています。
$start を幅で指定したい場合は一旦 mb_strimwidth() で任意の幅を切出し、その文字数を mb_strlen() でカウントしてからもう一度 mb_strimwidth() を使う必要があります (ちょっと困りものですね)。

第4引数 $trimmarker の注意点

$trimmarker の幅は第3引数 $width に含まれます。

$width の幅に $trimmarker を含みたくない場合は、下記のようにします。

内部文字エンコーディングの指定を忘れずに

マルチバイト文字列関数による文字数及び幅の処理は、内部文字エンコーディングに依存しています。内部文字エンコーディングと扱う文字列の文字コードが一致しない場合は正常に動作しませんので、必ず指定しましょう。また、ソースコード自体の文字コードの不一致も文字化けの原因になりますので注意しましょう。

予め mb_internal_encoding() で一度指定しておけば、以降内部文字エンコーディングに依存する関数は全てこれに従います。また、関数の引数でその都度文字コードを指定することもできます。

CSSを使う方法もある

ウェブブラウザ上で特定サイズ内に文字列を収めたい場合は、mb_strimwidth() ではなくCSSを使う方法もあります。

CSSでは、text-overflow: ellipsisoverflow: hidden を併用することで、指定されたボックス内に収まらないテキストは自動的に省略されます。こちらのほうがPHPで処理するよりも綺麗に収まりますが、複数行に対応させようとすると記述が複雑になる等の難点もあります。これらのプロパティの詳細は下記URLをご参照ください。

QooQ