【PHP】strposを初心者向けにわかりやすく解説!文字列検索の基本と実践コード例

はじめに

PHPで文字列を扱っていると、「特定の単語が含まれているかどうか」を調べたいことがあるのではないでしょうか。
たとえばユーザーが入力した文章に、不適切な単語が含まれていないかをチェックするときや、商品名の一部から候補を探すサジェスト機能を作るときなどが挙げられます。

そういったケースで便利なのが、strpos 関数です。
文字列の中から部分文字列の位置を探し出せるため、PHPでの基本的なテキスト処理によく利用されます。

本記事では、初心者の方でもイメージしやすい具体例とともに、PHPのstrpos関数の基本と応用的な使い方を丁寧にお伝えしていきます。
文字列を扱う場面は多いため、ぜひ習得してみてください。

この記事を読むとわかること

  • strposの基本的な役割と仕組み
  • 文字列の検索結果から得られる戻り値の扱い方
  • 実務で遭遇しやすい活用シーンの具体例
  • 初心者がハマりやすいエラー回避のポイント

strposの基本

strposとは

strpos は、指定した文字列の中から、探したい単語や記号などを検索し、その最初の位置を数値として返すPHPの関数です。
英語の “string position” の略をイメージすると覚えやすいでしょう。

検索処理は左から右へ順に行われ、見つかった最初の位置(インデックス)を返します。
ただし、文字列の先頭文字のインデックスは 0 となるので注意が必要です。

簡単な例を挙げると、「Hello World」という文字列の中に「World」という単語が含まれているかどうかを調べてみます。

<?php
$text = "Hello World";
$search = "World";

$position = strpos($text, $search);
echo $position; // 6 が表示される

このコードでは、文字列 "Hello World" の中で "World" は6文字目から始まっているため、strpos は 6 を返します。

文字列検索の仕組み

PHPの strpos は、第一引数に「検索対象の文字列」を、第二引数に「探したい文字列」を受け取ります。
このとき、もし探したい文字列が全く見つからなければ false が返されるという特徴があります。
0 が返るのと false が返るのは結果としての意味が異なるため、条件分岐でチェックするときは気をつける必要があります。

また、引数として オフセット (offset) を指定することもできます。
たとえば「文字列の先頭からある程度スキップして検索したい」という場合に、第3引数として整数値を渡せます。
こうした小回りの効く仕組みが、strposをより実用的にしているポイントと言えます。

strposの使い方と注意点

戻り値の扱い方

すでに少し触れましたが、戻り値は検索対象の文字列でのインデックス番号、もしくは false です。
これがほかの文字列処理と組み合わせるときに大事な意味を持ちます。

たとえば、何らかのキーワードが含まれていればそのキーワードの直後だけを抜き出す、といったときにインデックスを利用します。
一方で、見つからなかった場合は false なので、インデックスとして 0 が返ってきたわけではない、という区別が必要になるでしょう。

以下は、見つかった場合にそのキーワードより先の文字列を全て取り出す例です。

<?php
$text = "Email: user@example.com";
$search = "Email:";

$position = strpos($text, $search);

if ($position !== false) {
    // strposが返すインデックスに、検索する単語の長さを足してから文字列を切り出す
    $keywordLength = strlen($search);
    $result = substr($text, $position + $keywordLength);
    echo $result; // " user@example.com"
} else {
    echo "キーワードが見つかりませんでした。";
}

この例では、「Email:」というキーワードを見つけて、その位置と長さを元に文字列を切り出しています。
メールアドレス部分だけを取り出したい、といったケースで活用できるパターンです。

false と 0 の違い

初心者が特に戸惑いやすいのが「false と 0 をどう区別すればいいのか」という点です。
PHPでは、条件式の中で false0 はどちらも偽と判定されるため、if ($position == false) のように書いてしまうと、インデックスが 0 のときも誤って「見つからなかった」と判定してしまいます。

たとえば、以下のような文字列検索を考えてみます。

<?php
$text = "World is big";
$search = "World";

$position = strpos($text, $search);

if ($position == false) {
    echo "検索結果はありません";
} else {
    echo "検索結果はありました";
}

このように書くと、先頭のインデックスが0の場合も false とみなされてしまい、誤判定が起こります。
厳密な比較演算子 === を使うことで、 0false を明確に区別するのがおすすめです。

<?php
$text = "World is big";
$search = "World";

$position = strpos($text, $search);

if ($position === false) {
    echo "検索結果はありません";
} else {
    echo "検索結果はありました";
}

こう書くと、文字列の先頭に「World」がある場合は 0 が返るため、 if ($position === false) は偽と判定され、「検索結果はありました」が出力されます。

offset パラメータを使った検索

strpos の第3引数にあたる offset は、検索を開始する位置を示します。
これを指定すると、インデックス0からではなく、任意の位置から探索が始まります。

<?php
$text = "apple banana apple";
$search = "apple";

// 最初に見つかる"apple"はインデックス0
$firstPos = strpos($text, $search);
echo $firstPos; // 0

// offsetパラメータを使って検索開始位置を5以降にすると...
$secondPos = strpos($text, $search, 5);
echo $secondPos; // 13

上記の例では、最初の "apple" はインデックスが0なので $firstPos に 0 が入り、その後に offset=5 で検索を再開すると、今度は文字列後半にある "apple" がヒットして 13 が返ってきます。
部分文字列を複数回にわたって探したいケースでよく使うテクニックです。

実務での利用シーンと具体例

不適切ワードのフィルタリング

コメント投稿機能やチャットアプリを作る際に、不適切な単語が含まれているかをチェックしたい場合があります。
このとき、チェック対象の文字列に「禁止ワード」が含まれているかどうかを調べるのに strpos が活躍します。

<?php
$comment = "This is a bad comment!";
$ngWords = ["bad", "ugly"]; // 禁止ワードの例

foreach ($ngWords as $word) {
    if (strpos($comment, $word) !== false) {
        echo "不適切な言葉が含まれています。";
        // 適切な処理(投稿を拒否・警告表示など)を実施
        break;
    }
}

このように、ユーザーが入力した文章の中に特定の単語が存在するかどうかを高速に確認することができます。
もし strpos が false を返さなければ、何らかの措置を取る、という形です。

タグ抽出やテキストパース

たとえば、HTMLの断片から <div> タグが含まれているかどうかを簡易的に判断したい場合にも活用できます。
属性や複雑なネスト構造がなければ、単純に <div> の文字列を探すことでタグを含むかどうかを判定できます。

<?php
$htmlFragment = "<div>Example Text</div>";
if (strpos($htmlFragment, "<div>") !== false) {
    echo "divタグがあります";
}

もちろん、本格的なHTMLパースにはDOM操作系の機能などを使うのが確実ですが、シンプルな検索で済む場面では strpos のほうが手軽です。

部分一致サジェスト

商品名やユーザー名などで検索機能を作る際、ユーザーが入力したキーワードを含むデータを一覧表示したいことがあります。
これはデータベースレベルのSQL検索で処理するケースが多いですが、あまり大量でなければ配列にある文字列を strpos でチェックして抽出することも可能です。

<?php
$items = ["iPhone Case", "Android Charger", "Laptop Bag", "iPhone Cable"];
$keyword = "iPhone";

foreach ($items as $item) {
    if (strpos($item, $keyword) !== false) {
        echo $item . "\n";
    }
}

実際には検索結果をHTMLなどで整形して表示するなど、UIまわりと組み合わせることもよくあります。
それでも基本にあるのは strpos の検索機能です。

strposを使う上での注意点

マルチバイト文字列への配慮

日本語などのマルチバイト文字列を扱う場合、通常の strpos では文字化けや想定しないインデックス値が返る問題が起こることがあります。
マルチバイト対応の関数として mb_strpos が用意されており、同じような使い方をしながらも、文字のバイト数を考慮した検索ができます。

とはいえ、英数字や記号中心の検索であれば、標準の strpos でもほぼ問題なく動作します。
日本語環境でマルチバイト文字を扱う場合には、mb_strpos も検討するのが無難でしょう。

大文字・小文字を区別する

strpos は、大文字と小文字を区別して検索します。
つまり "HELLO" の中に "hello" を探しても見つかりません。

もしも大文字と小文字を区別しない検索が必要なときは stripos という関数が使えます。
i がついた名前で、大文字小文字を意識しない “case-insensitive” な検索になります。

<?php
$text = "Hello World";
$search = "hello";

// strposだと見つからない
var_dump(strpos($text, $search)); // bool(false)

// striposだと区別しないので、0が返る
var_dump(stripos($text, $search)); // int(0)

一度に複数のキーワードを探したいとき

複数の単語をまとめて探したい場合、先ほどのようなループ処理などを使って複数回のstrposを呼び出すのがシンプルなアプローチです。
検索対象が少量ならば性能面でも大きな問題はありません。
ただし、膨大な文字列に対して複数のキーワードを何度も検索するような場合は、他のアプローチやデータ構造を検討することもあります。

性能については、基本的な文字列検索にはstrposで十分なケースが多いです。
処理速度に余裕があれば、まずはstrposから始めてみるとよいでしょう。

よくあるエラーや混乱ポイント

戻り値の型を正しく比較しない

先述の通り、「if ($position == false) のような書き方が誤判定を生む」問題がよく起こります。
特に初心者のうちは、厳密比較演算子 === を使う癖をつけておくと安心です。
意図しない条件分岐を避けるためにも、この点は覚えておきましょう。

検索文字列が空のとき

誤って空文字列 "" を検索しようとすると、インデックス0を返したり挙動があいまいになるケースがあります。
一般的には「何も検索しない」ことになるため、ちゃんと実装段階で弾いておくと混乱を招きにくいです。

文字コードの不一致

ローカル環境やサーバー環境で文字コードが異なると、文字化けが原因でうまく見つからない場合があります。
マルチバイト文字列の場合は特に留意し、ファイルの文字コードや内部エンコーディングを揃えるようにしましょう。

実践的なサンプル:URLからドメインを抜き出す

ここでは、ちょっとした実務寄りの例として「URLの中からドメイン部分だけを抜き出す」イメージを見てみましょう。
実際には正規表現などを使う方法もありますが、strposとsubstrを組み合わせるやり方は意外とシンプルです。

<?php
function extractDomain($url) {
    // プロトコルの終了位置 "://" を探す
    $protocolEnd = strpos($url, "://");
    if ($protocolEnd === false) {
        // プロトコルなしのURLと仮定
        $domainStart = 0;
    } else {
        // プロトコルの終了文字までスキップ
        $domainStart = $protocolEnd + 3;
    }

    // 次にパスの開始位置 "/" を探す
    $pathStart = strpos($url, "/", $domainStart);
    if ($pathStart === false) {
        // パスが無ければURLの最後までがドメイン
        return substr($url, $domainStart);
    } else {
        // パスの手前までがドメイン
        return substr($url, $domainStart, $pathStart - $domainStart);
    }
}

// 使用例
$url = "https://www.example.com/products?item=phone";
$domain = extractDomain($url);
echo $domain; // "www.example.com"

この例のように、文字列内の特定位置を探しながら、一部分を抜き出す機能を自作したいときにも strpos は非常に便利です。
プロトコルやパスがあるかないかの条件分岐などで、=== false の使い方に慣れておくとバグを防げます。

strposで返るインデックスを使いこなすと、柔軟に部分文字列を切り出せます。
文字列を任意の区切りで分割したい、どこまでがドメインかだけを知りたい、などの要望にも対応しやすくなります。

まとめ

strpos は、PHPで文字列検索を行ううえで基本となる関数です。
特定の単語や記号を探し、最初に見つかった位置を返してくれるので、実務シーンでも頻繁に活用されます。

  • 見つかった場合は数値インデックス、見つからない場合は false を返す
  • 0false は厳密比較 === を使って区別する
  • offsetを使って検索開始位置を調整できる
  • 大文字小文字を区別したくない場合は stripos、日本語などのマルチバイトに注意がいる場合は mb_strpos
  • 不適切ワードの検知や、部分文字列の切り出しなど、多様なシーンで活用可能

こうしたポイントを押さえておけば、初心者の方でもPHPの文字列検索を円滑に進められるでしょう。
ぜひ一度、自分のコードにstrposを取り入れて、文字列処理をスムーズに組み立ててみてください。

PHPをマスターしよう

この記事で学んだPHPの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。