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

PHP PHP
スポンサーリンク

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

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

文字列: "ABC123"
キーワード: "ABC"   → 先頭が一致している(true)
キーワード: "AB"    → 先頭が一致している(true)
キーワード: "BC"    → 先頭ではないので前方一致ではない(false)

つまり、

「文字列の“先頭”が、指定した文字列で始まっているかどうか」

を調べるチェックです。

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

  • 会員番号が特定のプレフィックス(例: "VIP")で始まっているか
  • ファイル名が "log_" で始まるものだけ処理したい
  • URL が "https://api.example.com/" で始まるか確認したい

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


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

前方一致は、考え方としてはとてもシンプルです。

  1. 「調べたい文字列」の先頭から、キーワードと同じ長さだけ切り出す
  2. それがキーワードと同じなら「前方一致」

例えば、文字列 "ABC123" とキーワード "ABC" なら、

  • キーワードの長さは 3
  • 先頭3文字を切り出す → "ABC"
  • キーワード "ABC" と同じ → 前方一致(true)

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


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

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

substr() は、文字列の一部を切り出す関数です。

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

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

/**
 * 前方一致チェック:$haystack が $prefix で始まっているか
 *
 * @param string $haystack 調べたい文字列
 * @param string $prefix   先頭に来てほしい文字列
 * @return bool
 */
function startsWith(string $haystack, string $prefix): bool
{
    // プレフィックスが空文字なら、常に true とするかどうかは仕様次第
    if ($prefix === '') {
        return true;
    }

    // プレフィックスの長さを取得
    $len = strlen($prefix);

    // 先頭から同じ長さだけ切り出して比較
    return substr($haystack, 0, $len) === $prefix;
}
PHP

使い方はこうです。

var_dump(startsWith("ABC123", "ABC")); // true
var_dump(startsWith("ABC123", "AB"));  // true
var_dump(startsWith("ABC123", "BC"));  // false
var_dump(startsWith("ABC123", ""));    // true(ここは仕様次第)
PHP

やっていることは、

  • キーワードの長さを測る
  • その長さ分だけ先頭から切り出す
  • 完全一致かどうかを比較する

だけです。


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

strlen / substr の弱点

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

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

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

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

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

    $len = mb_strlen($prefix, 'UTF-8');

    return mb_substr($haystack, 0, $len, 'UTF-8') === $prefix;
}
PHP

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

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

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


strpos で書く方法との違いと注意点

strpos でも「前方一致」は書ける

strpos を使っても、前方一致は書けます。

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

    return strpos($haystack, $prefix) === 0;
}
PHP

ここでのポイントは、

  • 「見つかった位置」が 0 なら「先頭で見つかった」
  • なので === 0 で判定する

ということです。

ただし、strpos は「バイト位置」で動くので、
日本語を含む場合は mb_strpos を使う方が安全です。

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

    return mb_strpos($haystack, $prefix, 0, 'UTF-8') === 0;
}
PHP

初心者がハマりやすい罠

strpos を使うときに、こう書いてしまうとバグります。

if (mb_strpos($haystack, $prefix, 0, 'UTF-8')) {
    // 先頭で見つかったとき(位置 0)は false とみなされてしまう
}
PHP

0 は「先頭で見つかった」という意味ですが、
if (0) は false なので、この条件には入りません。

なので、strpos 系で前方一致を書くなら、
必ず === 0 で判定することが超重要です。


実務での使いどころ

会員番号のプレフィックス判定

$memberId = "VIP-12345";

if (startsWith($memberId, "VIP-")) {
    // VIP 会員として扱う
}
PHP

会員種別やコード体系で、「先頭の文字列で意味が変わる」設計はよくあります。

ファイル名のフィルタリング

$filename = "log_20260127.txt";

if (startsWith($filename, "log_")) {
    // ログファイルとして処理する
}
PHP

バッチ処理やログローテーションなどで、
「特定のプレフィックスを持つファイルだけ処理したい」ときに、そのまま使えます。

URL のチェック

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

if (!startsWith($url, "https://api.example.com/")) {
    throw new RuntimeException("許可されていない URL です");
}
PHP

外部から渡された URL が、自分の想定しているドメイン配下かどうかを、
ざっくりチェックする用途にも使えます(本格的なバリデーションは別途必要ですが)。


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

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

  • 前方一致は、「先頭からキーワードと同じ長さだけ切り出して比較する」と考えるとシンプル。
  • UTF-8 前提なら、mb_strlenmb_substr を使って実装するのが安全。
  • strpos / mb_strpos で書く場合は、必ず === 0 で判定する(ここを雑に書くと確実にバグる)。
  • 実務では、startsWith() のようなユーティリティ関数にしてしまうと、呼び出し側のコードが読みやすくなる。

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

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

    $len = mb_strlen($prefix, 'UTF-8');
    return mb_substr($haystack, 0, $len, 'UTF-8') === $prefix;
}
PHP

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