最近、蛍が飛んでるようです。以前から家の裏とかもちょこちょこ蛍が飛んでたりしてたんですが、自分が田舎に帰ってきた9年ぐらい前から、近くの川で蛍で本格的に乱舞するようになってます。
さて、PHPって、本当に親切な関数がたくさんあるんですが、mb_strimwidthもこんな親切でいいの!と思う関数のひとつですよね。
記事をリストに並べたりした時に、文字数を短く丸めたいときに好きな文字数で丸める上に「…」とか「(続く)」とか、丸めた時だけお尻に文字をつけられます。この処理が一行で出来るなんて便利!
パラメータは順番に
str
丸めたい文字列。
start
開始位置のオフセット。文字列の始めからの文字数 (最初の文字は 0) です。
width
丸める幅。
trimmarker
丸めた後にその文字列の最後に追加される文字列。
encoding
encoding
パラメータには文字エンコーディングを指定します。省略した場合は、 内部文字エンコーディングを使用します。
となっています。
1 |
echo mb_strimwidth("文字列が続くよ", 0, 9, "..."); |
実行結果:
1 |
文字列... |
ただ、mb_系のマルチバイト関数全体がそうですがちょっと使いづらいところもあり、自前で処理している人も多いとか。でもせっかくPHPの中にあるんなら、そっち使いたいです、わたしは。
mb_strimwidthのはまりポイントは2つ。
1.第3引数のwidthは文字数でもバイト数でもなく文字幅。
バイト数だったら、UTF-8の全角文字は3バイトになるところですがどの文字エンコードでも全角は2です。ここを間違うと意図したところで切れなくて困ります。
英数、半角カタカナは1と数えます。見た目の大きさを基準にしているということです。ただ、タブ文字とか改行も1と数えるので、単純に見た目とも言えなかったり。この辺は、プログラマなら分かるよね?…という目配せ的なアレですね。
2.第4引数のtrimmarkerの文字幅もwidthに含まれる
1 2 3 |
$trim_width = 13; // 取り出したい文字幅 $trimmarker = "..."; // 丸めた時に付加する文字列 $data = mb_strimwidth($data, 0, $trim_width+mb_strwidth($trimmarker), $trimmarker, 'UTF-8'); |
と書くと分かりやすいでしょうか、手順から考えると。
3.第5引数のencodingは必ず指定する、絶対。
とうとう、最後の第5引数まできちゃいました。マルチバイト関数の文字エンコーディング指定は分かる人はいちいち指定する必要もないんでしょうが、ね。
encodingは指定しなければ内部文字エンコーディングになるんですが、指定しておけば間違いないです。ここを間違った文字エンコーディングにすると文字化けします。
ちなみにmb_internal_encodingで事前に文字エンコーディングを指定してやるのも有効です。
ここまでやって、まだ不安だったので本当に文字化けしないか調べる時に使ったコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<h1>mb_strimwidthの実験</h1> <?php $data = "日本語\nニホンゴです、こんにちわ"; $trim_width = 13; $trimmarker = "..."; echo "<p>「{$data}」から{$trim_width}文字取り出します。{$trim_width}文字以上あれば「{$trimmarker}」をつけます</p>"; echo $data; $encode = mb_detect_encoding($data); $data = mb_strimwidth( $data, 0, $trim_width + mb_strwidth($trimmarker, $encode), $trimmarker, $encode); echo "▶︎".$data; echo "<br>"; $length = mb_strlen($data, $encode); $width = mb_strwidth($data); echo "<p>文字エンコーディング:".$encode."</p>"; echo "<p>変換後の文字数:".$length."</p>"; echo "<p>変換後の文字幅:".$width."</p>"; for ($i = 0; $i < $length; $i++){ $char = mb_substr($data, $i, 1, $encode); echo "<span style=\"padding:2px;\">".$char."</span>"; echo "<span style=\"color:gray;font-size:small;\">(".bin2hex($char).")</span>"; } ?> |
これをcloud9で文字列とか文字幅とかいろいろ変えてみて、バイナリレベルでみてみたのですが、変な事は起きませんでした。
参考:指定した文字数で文字列をまるめるPHPの関数 mb_strimwidth で、第4引数に「文字列をまるめた後に付加する文字列を指定」する際、色々気を付けないと文字化けるよ、というお話。