「指定文字数で省略(…付き)」がやりたいこと
やりたいことはシンプルです。
文字列が長すぎるときに、
「指定した文字数まで」で切り、
末尾に「…(三点リーダー)」を付けて短く見せる。
例えば、タイトルがこうだとします。
$title = "これはとてもとても長いお知らせタイトルです";
PHPこれを「10文字まで」にしたいなら、
これはとてもとても長いお知らせタイトルです
↓
これはとてもと…
のように、「10文字+…」という形にしたい、というユーティリティです。
ここで重要なのは、
- 日本語(マルチバイト)でも文字化けせずに切ること
- 途中で文字が欠けないようにすること
- 「すでに短い文字列」はそのまま返すこと
この3つです。
なぜ「マルチバイト対応」で省略しないといけないのか
strlen と substr でやると壊れる
まず、やってはいけないパターンから。
$title = "これはとてもとても長いお知らせタイトルです";
$short = substr($title, 0, 10); // ダメな例(バイト数で切ってしまう)
echo $short;
PHPsubstr は「バイト数」で切ります。
UTF-8 の日本語は 1文字が 3バイトなので、10バイトで切ると「文字の途中」で切れてしまい、
文字化けしたり、意味不明な文字列になったりします。
mb_substr と mb_strlen を使う
日本語を含む文字列を「人間の感覚どおり」に扱いたいときは、mb_strlen と mb_substr をセットで使うのが基本です。
mb_strlen:マルチバイト対応の「文字数カウント」mb_substr:マルチバイト対応の「部分文字列取得」
これを使えば、「何文字目まで」という単位で安全に切り出せます。
基本形:マルチバイト安全な「…付き省略」関数
まずは完成形を見てみる
実務でそのまま使える、シンプルな関数を先に出します。
/**
* 指定文字数を超える場合に「…」を付けて省略する(UTF-8 前提)
*
* @param string $text 対象文字列
* @param int $limit 最大文字数
* @return string 省略後の文字列
*/
function truncateWithEllipsis(string $text, int $limit): string
{
// 現在の文字数を取得
$length = mb_strlen($text, 'UTF-8');
// 文字数が制限以内なら、そのまま返す
if ($length <= $limit) {
return $text;
}
// 指定文字数だけ切り出す
$truncated = mb_substr($text, 0, $limit, 'UTF-8');
// 末尾に「…」を付ける
return $truncated . '…';
}
PHP使い方はこうです。
$title = "これはとてもとても長いお知らせタイトルです";
echo truncateWithEllipsis($title, 10);
// これはとてもと…
PHPここから、この関数の中身をかみ砕いて説明していきます。
関数の中身を一つずつ分解して理解する
1. まず「今の文字数」を数える
$length = mb_strlen($text, 'UTF-8');
PHPここでやっているのは、
「この文字列は、今何文字あるのか?」
を、マルチバイト対応で数えることです。
strlenではなくmb_strlenを使う- エンコーディング
'UTF-8'を明示する
この2つがとても重要です。
2. そもそも短いなら、そのまま返す
if ($length <= $limit) {
return $text;
}
PHPここは地味ですが、実務ではかなり大事な分岐です。
- すでに 10文字以内のタイトルを、わざわざ「…」付きにする必要はない
- 「短いものはそのまま」「長いものだけ省略」というのが自然な挙動
なので、「制限以内なら何もしないで返す」というのが正解です。
3. 指定文字数だけ安全に切り出す
$truncated = mb_substr($text, 0, $limit, 'UTF-8');
PHPmb_substr は、「開始位置」と「長さ」を「文字数単位」で指定できます。
- 第1引数:元の文字列
- 第2引数:開始位置(0 なら先頭から)
- 第3引数:取得したい文字数
- 第4引数:エンコーディング(ここでも
'UTF-8'を明示)
これで、「先頭から $limit 文字分だけ」を安全に切り出せます。
4. 最後に「…」を付ける
return $truncated . '…';
PHPここで付けているのは、全角の三点リーダー(…)です。
半角の ... にしたい場合は、ここを '...' に変えれば OK です。
実務での具体的なシチュエーション例
例題1:記事タイトルの一覧表示
一覧画面で、タイトルが長すぎるとレイアウトが崩れるので、
「最大 20 文字まで」にしたいケースを考えます。
$title = $row['title'];
$shortTitle = truncateWithEllipsis($title, 20);
echo htmlspecialchars($shortTitle, ENT_QUOTES, 'UTF-8');
PHPここでのポイントは、
- 省略処理(
truncateWithEllipsis)は「生の文字列」に対して行う - 画面に出すときは、最後に
htmlspecialcharsでエスケープする
という順番です。
例題2:本文の冒頭だけを「要約」として表示
本文は長いけれど、一覧では「冒頭 50 文字だけ」を見せたい、というケース。
$body = $row['body']; // HTML ではなくプレーンテキスト前提の例
$summary = truncateWithEllipsis($body, 50);
echo nl2br(htmlspecialchars($summary, ENT_QUOTES, 'UTF-8'));
PHP本文がプレーンテキストなら、このまま使えます。
HTML の場合は、先にタグ除去やテキスト化が必要になりますが、
「テキストになったあと」の省略処理は同じです。
もう少しだけ踏み込んだ工夫
「…」も含めて「全体で N 文字」にしたい場合
今の関数は、
- 本文:
$limit文字 - そのあとに「…」
なので、全体の長さは $limit + 1 文字になります。
もし、
「“本文+…” を合わせて 10 文字以内にしたい」
という場合は、本文部分を 1 文字減らせばよいです。
function truncateWithEllipsisStrict(string $text, int $limit): string
{
$length = mb_strlen($text, 'UTF-8');
if ($length <= $limit) {
return $text;
}
// 「…」の分を 1 文字引く
$bodyLength = max($limit - 1, 0);
$truncated = mb_substr($text, 0, $bodyLength, 'UTF-8');
return $truncated . '…';
}
PHPこの場合、$limit が 10 なら、
- 本文:9文字
- 「…」:1文字
で、合計 10 文字になります。
末尾の空白や改行を整えてから省略する
省略前に、前後の空白や改行を整えておくと、見た目がきれいになります。
function truncateWithEllipsisTrimmed(string $text, int $limit): string
{
// 前後の空白や改行を削る
$text = trim($text);
$length = mb_strlen($text, 'UTF-8');
if ($length <= $limit) {
return $text;
}
$truncated = mb_substr($text, 0, $limit, 'UTF-8');
return $truncated . '…';
}
PHPまとめ:今日からの「省略処理」の基準
押さえておきたいポイントだけ、最後にコンパクトに整理します。
- 日本語を含む文字列を「指定文字数で省略」するときは、
strlen/substrではなく、必ずmb_strlen/mb_substrを使う。 - 「短い文字列はそのまま返す」「長いときだけ“…付き”にする」という分岐を入れる。
- 「…」を含めた全体の長さをどうしたいか(
limitに含めるかどうか)を、最初に決めておく。
