「指定文字数で省略(省略記号なし)」がやりたいこと
ここでやりたいのは、とてもシンプルです。
文字列が長すぎるときに、
「指定した文字数まで」でバッサリ切る。
末尾に「…」などの省略記号は付けない。
例えば、タイトルがこうだとします。
$title = "これはとてもとても長いお知らせタイトルです";
PHPこれを「10文字まで」にしたいなら、
これはとてもとても長いお知らせタイトルです
↓
これはとてもと
のように、「先頭から 10 文字だけ」を残して、それ以降は捨てる、というユーティリティです。
ここで一番大事なのは、「日本語を安全に切る」ことです。
つまり、文字の途中で切って文字化けさせない、ということです。
なぜ「マルチバイト対応」で省略しないといけないのか
strlen / substr でやると壊れる理由
まず、やってはいけないパターンから見てみます。
$title = "これはとてもとても長いお知らせタイトルです";
$short = substr($title, 0, 10); // ダメな例(バイト数で切る)
echo $short;
PHPsubstr は「バイト数」で切ります。
UTF-8 の日本語は 1文字が 3バイトなので、10バイトで切ると「文字の途中」で切れてしまい、
結果として文字化けしたり、意味不明な文字列になります。
「日本語を含む文字列」を扱うときに、substr をそのまま使うのは基本的にアウトです。
mb_substr / mb_strlen を使うのが必須
日本語を含む文字列を「人間の感覚どおり」に扱いたいときは、
- 文字数を数えるとき:
mb_strlen - 一部を切り出すとき:
mb_substr
このセットを使うのが基本です。
mb_ が付いている関数は「マルチバイト文字列用」で、
UTF-8 の日本語でも「1文字は1文字」として扱ってくれます。
基本形:マルチバイト安全な「指定文字数で切る」関数
まずは完成形を見てみる
実務でそのまま使える、シンプルな関数を先に出します。
/**
* 指定文字数でバッサリ省略(省略記号なし・UTF-8 前提)
*
* @param string $text 対象文字列
* @param int $limit 最大文字数
* @return string 省略後の文字列
*/
function truncatePlain(string $text, int $limit): string
{
// 現在の文字数を取得
$length = mb_strlen($text, 'UTF-8');
// 文字数が制限以内なら、そのまま返す
if ($length <= $limit) {
return $text;
}
// 指定文字数だけ切り出す
return mb_substr($text, 0, $limit, 'UTF-8');
}
PHP使い方はこうです。
$title = "これはとてもとても長いお知らせタイトルです";
echo truncatePlain($title, 10);
// これはとてもと
PHPここから、この関数の中身を一つずつかみ砕いていきます。
関数の中身を分解して理解する
1. まず「今の文字数」を数える
$length = mb_strlen($text, 'UTF-8');
PHPここでやっているのは、
「この文字列は、今何文字あるのか?」
を、マルチバイト対応で数えることです。
ポイントは2つです。
strlenではなくmb_strlenを使うこと- エンコーディング
'UTF-8'を明示すること
これで、日本語を含んでいても「人間の感覚どおりの文字数」が取れます。
2. そもそも短いなら、そのまま返す
if ($length <= $limit) {
return $text;
}
PHPここは地味ですが、とても大事です。
- すでに 10文字以内のタイトルを、わざわざ切る必要はない
- 「短いものはそのまま」「長いものだけ切る」というのが自然な挙動
なので、「制限以内なら何もしないで返す」という分岐を必ず入れます。
3. 指定文字数だけ安全に切り出す
return mb_substr($text, 0, $limit, 'UTF-8');
PHPmb_substr は、「開始位置」と「長さ」を「文字数単位」で指定できます。
- 第2引数:開始位置(0 なら先頭から)
- 第3引数:取得したい文字数
- 第4引数:エンコーディング
これで、「先頭から $limit 文字分だけ」を安全に切り出せます。substr と違って「文字の途中で切れる」ことがないのが、最大のポイントです。
実務での具体的なシチュエーション例
例題1:一覧画面のタイトルを「きっちり 20 文字まで」にしたい
一覧画面で、タイトルが長すぎるとレイアウトが崩れるので、
「20文字を超えた分は、単純に切り捨てたい」というケース。
$title = $row['title'];
$shortTitle = truncatePlain($title, 20);
echo htmlspecialchars($shortTitle, ENT_QUOTES, 'UTF-8');
PHPここでのポイントは、
- 省略処理は「生の文字列」に対して行う
- 画面に出すときは、最後に
htmlspecialcharsでエスケープする
という順番です。
例題2:CSV 出力用に「固定幅の項目」に収めたい
外部システム向けに CSV や固定長ファイルを出力するとき、
「この項目は最大 10 文字まで」と決まっていることがあります。
$name = $row['name']; // ユーザー名など
$name = truncatePlain($name, 10);
// あとは CSV の1カラムとして出力
PHPこのとき、substr でバイト数で切ってしまうと、日本語が途中で切れて文字化けします。truncatePlain のような「マルチバイト安全な省略」を使うことで、
「見た目の文字単位」で安全に収めることができます。
もう少しだけ踏み込んだ工夫
前後の空白や改行を整えてから省略する
省略前に、前後の空白や改行を整えておくと、見た目がきれいになります。
function truncatePlainTrimmed(string $text, int $limit): string
{
// 前後の空白や改行を削る
$text = trim($text);
$length = mb_strlen($text, 'UTF-8');
if ($length <= $limit) {
return $text;
}
return mb_substr($text, 0, $limit, 'UTF-8');
}
PHPこれなら、「末尾に変なスペースが残ったまま切れる」といったことを防げます。
「バイト数で切りたい」ケースとの切り分け
ごくまれに、「文字数ではなくバイト数で切りたい」ケースもあります(プロトコルや古い仕様など)。
その場合は、あえて substr や strlen を使うこともありますが、
それは「バイト数が欲しい」と明確に分かっているときだけに限定するのが安全です。
普段のアプリ開発では、
「人間が読む文字列」=
mb_strlen/mb_substr
「バイナリやプロトコル」=strlen/substr
という使い分けを意識しておくと、混乱しにくくなります。
まとめ:今日からの「省略処理」の基本形
押さえておきたいポイントをコンパクトにまとめると、こうなります。
- 日本語を含む文字列を「指定文字数で省略」するときは、
strlen/substrではなく、必ずmb_strlen/mb_substrを使う。 - 「短い文字列はそのまま返す」「長いときだけ切る」という分岐を入れる。
- 省略記号が不要なら、単純に
mb_substrの結果を返せばよい。
そして、実務ユーティリティとしては、この関数をプロジェクト共通で置いておくとかなり便利です。
function truncatePlain(string $text, int $limit): string
{
$length = mb_strlen($text, 'UTF-8');
if ($length <= $limit) {
return $text;
}
return mb_substr($text, 0, $limit, 'UTF-8');
}
PHP