💡 今日の3行まとめ
  • substr() や strlen() はバイト数で処理するため、日本語(UTF-8)が文字化けする
  • mb_strimwidth() を使えば、指定した表示幅を超えたときだけ自動で末尾に ... を付けて丸められる
  • 日本語の正確な文字数をカウントするときは、必ず mb_strlen() を使う

1. 今日のお題とゴール

ブログの記事タイトル一覧を表示するとき、長すぎるタイトルだけ末尾を ... で省略し、横に元の文字数を添えて出力する処理を書いてみましょう。

  • 各タイトルの正確な文字数を mb_strlen() で取得する
  • 表示幅が半角24文字分(全角12文字分)を超えるタイトルだけ、末尾を ... に丸める
  • 短いタイトルには ... を付けず、そのまま表示する
// 期待する出力例
PHP入門(全5文字)
PHP8で学ぶWebアプリ開...(全26文字)
HTMLとCSSの基本まとめ(全14文字)

2. ❌ やりがちなNGコード vs ⭕ コピペで動く正解コード

❌ やりがちなNGコードBefore
<?php
$title = 'PHP8で学ぶWebアプリ開発!初心者向け実践ガイド';

// バイト数で切り取る substr() は日本語の途中で切れて文字化けする
echo substr($title, 0, 20) . '...';
// 出力: PHP8で学ぶWebア...

// strlen() も文字数ではなくバイト数(64)を返してしまう
echo strlen($title) . '文字'; // 出力: 64文字(実際は26文字)

substr() や strlen() は「文字数」ではなく「バイト数」で処理するため、1文字3バイトの日本語(UTF-8)が途中で切断されて文字化けします。また、末尾に . '...' を直接つなぐと、短いタイトルにまで ... が付いてしまいます。

⭕ コピペで動く正解コード(PHP 8.3+)After
<?php
declare(strict_types=1);

$titles = [
    'PHP入門',
    'PHP8で学ぶWebアプリ開発!初心者向け実践ガイド',
    'HTMLとCSSの基本まとめ',
];

$maxWidth = 24; // 最大表示幅(半角24文字=全角12文字分)

foreach ($titles as $title) {
    // 1. マルチバイト対応で正確な文字数を数える
    $length = mb_strlen($title, 'UTF-8');

    // 2. 指定幅を超える場合だけ末尾を「...」に丸める
    $shortTitle = mb_strimwidth($title, 0, $maxWidth, '...', 'UTF-8');

    // 3. 整形したタイトルと元の文字数を出力
    echo "{$shortTitle}(全{$length}文字)" . PHP_EOL;
}

3. ここだけ押さえる!3つのポイント

1省略表示は mb_strimwidth() 1行で完結する

mb_strimwidth($title, 0, 24, '...') は、指定した幅を超えたときだけ末尾を ... に置き換えてくれます。短い文字列には ... が付かないため、面倒な if 文での分岐が不要になります。

2半角1・全角2の「見た目幅」で揃えられる

mb_strimwidth() は半角英数字を幅1、全角日本語を幅2として計算し、末尾の ...(幅3)を含めて指定幅に収めます。英数字と日本語が混ざる記事タイトルでも、一覧画面で横幅がピタッと揃うのが大きな強みです。

3文字数カウントには必ず mb_strlen() を使う

UTF-8の日本語は1文字で3バイトあるため、strlen() を使うと3倍近い数値が返ってしまいます。日本語の文字数を正確に数えるときは、必ずマルチバイト対応の mb_strlen() を使いましょう。

4. 1分ミニチャレンジ

🚀 手を動かしてみよう

正解コードの $maxWidth = 24; の1行を $maxWidth = 14; に変えて実行してみましょう。
ヒント:さきほどはそのまま表示されていた3つ目の『HTMLとCSSの基本まとめ』も、幅14に収まるよう HTMLとCSSの... に自動で丸められます!