PHP Tips | 文字列処理:文字数・切り出し – 指定文字数で省略(省略記号なし)

PHP PHP
スポンサーリンク

「指定文字数で省略(省略記号なし)」がやりたいこと

ここでやりたいのは、とてもシンプルです。

文字列が長すぎるときに、
「指定した文字数まで」でバッサリ切る。
末尾に「…」などの省略記号は付けない。

例えば、タイトルがこうだとします。

$title = "これはとてもとても長いお知らせタイトルです";
PHP

これを「10文字まで」にしたいなら、

これはとてもとても長いお知らせタイトルです
↓
これはとてもと

のように、「先頭から 10 文字だけ」を残して、それ以降は捨てる、というユーティリティです。

ここで一番大事なのは、「日本語を安全に切る」ことです。
つまり、文字の途中で切って文字化けさせない、ということです。


なぜ「マルチバイト対応」で省略しないといけないのか

strlen / substr でやると壊れる理由

まず、やってはいけないパターンから見てみます。

$title = "これはとてもとても長いお知らせタイトルです";

$short = substr($title, 0, 10);  // ダメな例(バイト数で切る)

echo $short;
PHP

substr は「バイト数」で切ります。
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');
PHP

mb_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

これなら、「末尾に変なスペースが残ったまま切れる」といったことを防げます。

「バイト数で切りたい」ケースとの切り分け

ごくまれに、「文字数ではなくバイト数で切りたい」ケースもあります(プロトコルや古い仕様など)。
その場合は、あえて substrstrlen を使うこともありますが、
それは「バイト数が欲しい」と明確に分かっているときだけに限定するのが安全です。

普段のアプリ開発では、

「人間が読む文字列」= 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

タイトルとURLをコピーしました