PHP Tips | 文字列処理:検索・置換 – 後方一致チェック

PHP PHP
スポンサーリンク

「後方一致チェック」でやりたいことをまずイメージする

「後方一致」は、こういう判定のことです。

文字列: "report.csv"
キーワード: ".csv"  → 最後が一致している(true)
キーワード: "csv"   → 最後が一致している(true)
キーワード: ".txt"  → 最後が一致していない(false)

つまり、

「文字列の“末尾”が、指定した文字列で終わっているかどうか」

を調べるチェックです。

業務だと、例えばこんな場面でよく使います。

  • ファイル名が「.csv」「.txt」など、特定の拡張子で終わっているか
  • URL が「/api」で終わるエンドポイントかどうか
  • コードやIDが特定のサフィックス(例: -TEST)で終わっているか

「含まれているか」でも「先頭」でもなく、「最後がそれかどうか」がポイントです。


基本の考え方:末尾の部分だけを切り出して比べる

前方一致のときは「先頭から N 文字」でしたが、
後方一致は「末尾から N 文字」です。

考え方はシンプルで、

  1. キーワードの長さを測る
  2. 文字列の末尾から、その長さ分だけ切り出す
  3. それがキーワードと同じなら「後方一致」

例えば、文字列 "report.csv" とキーワード ".csv" なら、

  • キーワードの長さは 4
  • 末尾4文字を切り出す → ".csv"
  • キーワードと同じ → 後方一致(true)

この「末尾から N 文字切り出して比較する」を、PHP でどう書くかを見ていきます。


まずは substr で素直に書いてみる

substr を使った後方一致チェック

substr() は、負のオフセットを使うと「末尾から」の切り出しができます。

string substr(string $string, int $offset, ?int $length = null)
PHP

$offset に負の値を渡すと、「末尾から数えた位置」になります。

substr("report.csv", -4); // ".csv"
PHP

これを使って、後方一致チェックを書くとこうなります。

/**
 * 後方一致チェック:$haystack が $suffix で終わっているか
 *
 * @param string $haystack 調べたい文字列
 * @param string $suffix   最後に来てほしい文字列
 * @return bool
 */
function endsWith(string $haystack, string $suffix): bool
{
    // サフィックスが空文字なら、常に true とするかどうかは仕様次第
    if ($suffix === '') {
        return true;
    }

    $len = strlen($suffix);

    // 文字列全体よりサフィックスの方が長いなら、絶対に一致しない
    if ($len > strlen($haystack)) {
        return false;
    }

    // 末尾から同じ長さだけ切り出して比較
    return substr($haystack, -$len) === $suffix;
}
PHP

使い方はこうです。

var_dump(endsWith("report.csv", ".csv")); // true
var_dump(endsWith("report.csv", "csv"));  // true
var_dump(endsWith("report.csv", ".txt")); // false
var_dump(endsWith("a", "abc"));           // false
var_dump(endsWith("report.csv", ""));     // true(ここは仕様次第)
PHP

やっていることは、

  • サフィックスの長さを測る
  • 文字列全体より長ければ即 false
  • 末尾からその長さ分だけ切り出す
  • 完全一致かどうかを比較する

だけです。


日本語・UTF-8 をちゃんと扱うなら mb_substr / mb_strlen

strlen / substr の弱点

strlen / substr は「バイト数」で動きます。
UTF-8 の日本語を扱うと、「文字数」としての長さ・位置がズレることがあります。

例えば、 "本日は晴天" のような文字列は、
1文字が3バイトだったりするので、「バイト数」と「文字数」が一致しません。

「後方一致」では、「見た目の文字単位」で考えたいことが多いので、
UTF-8 前提なら mb_strlen / mb_substr を使う方が安全です。

mb_* を使った後方一致チェック

function endsWith(string $haystack, string $suffix): bool
{
    if ($suffix === '') {
        return true;
    }

    $lenSuffix  = mb_strlen($suffix, 'UTF-8');
    $lenHaystack = mb_strlen($haystack, 'UTF-8');

    if ($lenSuffix > $lenHaystack) {
        return false;
    }

    // 末尾から lenSuffix 文字を切り出す
    $tail = mb_substr($haystack, -$lenSuffix, null, 'UTF-8');

    return $tail === $suffix;
}
PHP

これなら、日本語でも安心して使えます。

var_dump(endsWith("本日は晴天なり", "晴天なり")); // true
var_dump(endsWith("本日は晴天なり", "晴天"));     // false
PHP

UTF-8 のプロジェクトなら、
「文字列処理は最初から mb_* に寄せる」と決めてしまうのがおすすめです。


strpos で書く方法との違い

「最後に出てくる位置」を使うという発想

strpos の兄弟に strrpos(最後に出てくる位置を返す)があります。

int|false strrpos(string $haystack, string $needle)
PHP

これを使っても、後方一致は書けます。

function endsWithByStrrpos(string $haystack, string $suffix): bool
{
    if ($suffix === '') {
        return true;
    }

    $pos = strrpos($haystack, $suffix);

    if ($pos === false) {
        return false;
    }

    // 「最後に見つかった位置」+「サフィックスの長さ」が
    // 文字列全体の長さと一致していれば、末尾で一致している
    return $pos + strlen($suffix) === strlen($haystack);
}
PHP

ただし、これも「バイト数」で動くので、
UTF-8 では mb_strrpos / mb_strlen を使う方が安全です。

とはいえ、「末尾から切り出して比較する」方が直感的で読みやすいので、
初心者向け・チーム開発では mb_substr 版をおすすめします。


実務での使いどころ

ファイル拡張子のチェック

$filename = "report_20260127.csv";

if (!endsWith($filename, ".csv")) {
    throw new RuntimeException("CSV ファイルのみアップロード可能です");
}
PHP

アップロードファイルの簡易チェックなどで、
拡張子を見て判定する場面はとても多いです(本格的には MIME タイプも見るべきですが)。

URL の末尾パスのチェック

$url = "https://example.com/api/users";

if (endsWith($url, "/users")) {
    // /users で終わるエンドポイントとして扱う
}
PHP

ルーティングや簡易判定で、「特定のパスで終わる URL かどうか」を見たいときに使えます。

コードやIDのサフィックス判定

$code = "ABC-TEST";

if (endsWith($code, "-TEST")) {
    // テスト用コードとして扱う
}
PHP

テストデータや一時データを、サフィックスで区別しているような設計でも役立ちます。


まとめ:今日からの「後方一致チェック」ユーティリティ

押さえておきたいポイントをコンパクトにまとめます。

  • 後方一致は、「末尾からキーワードと同じ長さだけ切り出して比較する」と考えるとシンプル。
  • UTF-8 前提なら、mb_strlenmb_substr を使って実装するのが安全。
  • 文字列全体よりサフィックスの方が長い場合は、即 false にできる。
  • 実務では、endsWith() のようなユーティリティ関数にしてしまうと、呼び出し側のコードが読みやすくなる。

まずは、この関数を一つプロジェクトに置いておくと、かなり使い回せます。

function endsWith(string $haystack, string $suffix): bool
{
    if ($suffix === '') {
        return true;
    }

    $lenSuffix   = mb_strlen($suffix, 'UTF-8');
    $lenHaystack = mb_strlen($haystack, 'UTF-8');

    if ($lenSuffix > $lenHaystack) {
        return false;
    }

    return mb_substr($haystack, -$lenSuffix, null, 'UTF-8') === $suffix;
}
PHP

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