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

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

mb_strimwidthの引数
string mb_strimwidth ( string $str , int $start , int $width [, string $trimmarker = "" [, string $encoding = mb_internal_encoding() ]] )

mb_strimwidthの「幅」とは

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

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

第2引数 $startの注意点

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

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

<?php
// 3文字目から幅6相当の文字列を取得
$s = mb_strimwidth('さんぷるabcde', 2, 6);

// $s = 'ぷるab'

第4引数 $trimmarkerの注意点

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

<?php
$s = mb_strimwidth('さんぷるabcde', 2, 6, '..');

// $s = 'ぷる..'

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

<?php
$s = mb_strimwidth('さんぷるabcde', 2, 6).'..';

// $s = 'ぷるab..'

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

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

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

<?php
// UTF-8の場合
mb_internal_encoding('UTF-8');

// SJIS(Windows)の場合
mb_internal_encoding('CP932');

CSSを使う方法もある

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

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

テーマ: プログラミング - ジャンル: コンピュータ

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバックURLはこちら
http://itpc.blog87.fc2.com/tb.php/180-0f7c44f6
この記事にトラックバック(FC2ブログユーザ用)