【PHP8.x】mb_strpos関数の使い方

作成日: 更新日:

mb_strpos関数は、特定の文字列が別の文字列内で最初に現れる位置を検索する関数です。この関数は、日本語や中国語など、一文字が複数のバイトで構成されるマルチバイト文字を正確に処理するために特別に設計されています。従来のstrpos関数がバイト単位で位置を数えるため、マルチバイト文字を扱う際に予期せぬ結果を招く可能性があるのに対し、mb_strpos関数は文字単位で位置を計算するため、文字化けや誤った位置の特定を防ぎ、安全で信頼性の高い文字列操作を実現します。

第一引数には検索の対象となる文字列を、第二引数には検索したい文字列を指定します。オプションの第三引数offsetを使用すると、検索を開始する位置を文字数単位で指定できます。さらに、第四引数encodingで、使用する文字エンコーディングを明示的に指定することも可能です。encodingを省略した場合、PHPの内部エンコーディングが自動的に使用されます。

検索文字列が見つかった場合、その文字列が対象文字列内で最初に開始する位置(0から始まるインデックス)が整数値で返されます。もし検索文字列が見つからなかった場合はfalseが返されます。検索文字列が対象文字列の先頭で見つかった場合、戻り値は0となります。このため、検索が成功したかどうかを正確に判断するには、戻り値とfalseの厳密な比較(=== false)を行うことが非常に重要です。この関数は、ウェブアプリケーション開発などでマルチバイト文字列の処理が必要な場面で広く活用されます。

基本的な使い方

構文(syntax)

<?php

$haystack = "こんにちは、世界!";
$needle = "世界";

$position = mb_strpos($haystack, $needle);

?>

引数(parameters)

string $haystack, string $needle, int $offset = 0, ?string $encoding = null

  • string $haystack: 検索対象となる文字列
  • string $needle: 検索する文字列
  • int $offset = 0: 検索を開始する位置(0から始まるインデックス)。省略した場合は文字列の先頭から検索します。
  • ?string $encoding = null: 文字エンコーディングを指定する文字列。指定しない場合は内部エンコーディングが使用されます。

戻り値(return)

int|false

指定された文字列が、対象の文字列内で最初に出現する位置(オフセット)をバイト数で返します。見つからなかった場合は false を返します。

サンプルコード

mb_strposでマルチバイト文字を検索する

<?php

/**
 * PHPのmb_strpos関数の基本的な使い方と、
 * マルチバイト文字列におけるstrpos関数との違いを示すサンプルコードです。
 * システムエンジニアを目指す初心者の方が「mb_strpos not working」という
 * 問題に直面した際の理解を助けることを目的としています。
 */
function demonstrateMbStrposUsage(): void
{
    // 検索対象のマルチバイト文字列(日本語を含む)
    $haystack = "こんにちは世界、PHPの世界へようこそ!";
    // 検索する部分文字列
    $needle = "世界";
    // 見つからない部分文字列
    $notFoundNeedle = "Python";

    echo "検索対象の文字列: \"" . $haystack . "\"\n\n";

    // --- strpos の問題点 (マルチバイト文字列の場合) ---
    // strpos はバイト単位で文字列を処理するため、日本語のようなマルチバイト文字を含む文字列では
    // 期待通りの結果(文字オフセット)が得られないことがあります。
    // これが「mb_strpos not working」と感じる原因の一つです。
    echo "--- strpos を使用した例 (非推奨) ---\n";
    $posStrpos = strpos($haystack, $needle);
    if ($posStrpos !== false) {
        // strposはバイトオフセットを返します。多くの場合、期待する文字オフセットとは異なります。
        echo "strpos で \"" . $needle . "\" を検索: 位置 " . $posStrpos . " (バイトオフセット)\n";
    } else {
        // 日本語文字列では、strposが正しく検索できない場合があります。
        echo "strpos で \"" . $needle . "\" は見つかりませんでした (期待通りの結果ではないかもしれません)。\n";
    }
    echo "\n";

    // --- mb_strpos の使い方 (マルチバイト文字列で推奨) ---
    // mb_strpos はマルチバイトセーフな関数で、文字単位で文字列を処理します。
    echo "--- mb_strpos を使用した例 (推奨) ---\n";

    // 1. 検索文字列が見つかる場合
    $posMbStrpos = mb_strpos($haystack, $needle);
    if ($posMbStrpos !== false) {
        // mb_strpos は0から始まる文字オフセットを返します。
        // 例: "こ"(0) "ん"(1) "に"(2) "ち"(3) "は"(4) "世"(5) -> '世界'は5番目の文字から始まる
        echo "mb_strpos で \"" . $needle . "\" を検索: 位置 " . $posMbStrpos . " (0始まりの文字オフセット)\n";
    } else {
        // 通常、このケースでは見つかるはずですが、念のため
        echo "mb_strpos で \"" . $needle . "\" は見つかりませんでした。\n";
    }

    // 2. 検索文字列が見つからない場合
    $posMbStrposNotFound = mb_strpos($haystack, $notFoundNeedle);
    if ($posMbStrposNotFound !== false) {
        echo "mb_strpos で \"" . $notFoundNeedle . "\" を検索: 位置 " . $posMbStrposNotFound . "\n";
    } else {
        // 検索文字列が見つからない場合、mb_strpos は false を返します。
        // 0 (文字列の先頭で見つかった場合) と false を厳密に区別することが重要です。
        echo "mb_strpos で \"" . $notFoundNeedle . "\" は見つかりませんでした (期待通り false が返ります)。\n";
    }

    // 3. 検索開始位置 (offset) の指定
    echo "\n--- mb_strpos でオフセットを指定した例 ---\n";
    // 最初の '世界' の次から検索を開始し、2つ目の '世界' を見つける例
    $firstWorldPos = mb_strpos($haystack, $needle); // 最初の '世界' の位置 (文字オフセット5)
    if ($firstWorldPos !== false) {
        // 検索開始位置は、最初の '世界' の直後からとします。
        // mb_strlenで'世界'の文字数を取得し、オフセットを計算します。
        $offset = $firstWorldPos + mb_strlen($needle); // 例: 5 + 2 = 7
        $secondWorldPos = mb_strpos($haystack, $needle, $offset);
        if ($secondWorldPos !== false) {
            echo "オフセット " . $offset . " から次の \"" . $needle . "\" を検索: 位置 " . $secondWorldPos . "\n";
            // 結果: "こんにちは世界、PHPの世界へようこそ!" 中の2つ目の'世界'は、文字オフセット12から始まる。
        } else {
            echo "オフセット " . $offset . " 以降に \"" . $needle . "\" は見つかりませんでした。\n";
        }
    } else {
        echo "最初の \"" . $needle . "\" が見つからなかったため、オフセット検索は行いませんでした。\n";
    }

    // 補足: encoding 引数について
    // 通常はPHPの内部エンコーディング (mb_internal_encoding() で設定) が使用されます。
    // 異なるエンコーディングの文字列を明示的に扱う場合は、第四引数で指定できます。
    // 例: mb_strpos($haystack, $needle, 0, 'EUC-JP');
    // ただし、haystackとneedleのエンコーディングが一致している必要があります。
}

// 関数を実行
demonstrateMbStrposUsage();

mb_strpos関数は、PHP 8.4で利用できる、マルチバイト文字列(日本語など)から特定の部分文字列が最初に現れる位置を、文字数で検索するための関数です。一般的なstrpos関数が文字列をバイト単位で処理するのに対し、mb_strposは文字単位で処理します。そのため、日本語のようなマルチバイト文字を含む文字列を扱う際に、正確な文字位置(オフセット)を取得するために推奨されます。strposをマルチバイト文字列に適用して意図しない結果となり、「mb_strpos not working」といった誤解が生じるケースがありますが、これはstrposがバイトオフセットを返すのに対し、mb_strposは文字オフセットを返すためです。

この関数は、最初の引数$haystackに検索対象の文字列、二番目の引数$needleに検索したい部分文字列を指定します。三番目の引数$offsetでは、検索を開始する文字位置を0から始まる整数で指定できます(デフォルトは0)。四番目の引数$encodingは、文字列のエンコーディングを明示的に指定する場合に使用しますが、通常はPHPの内部エンコーディングが適用されます。

戻り値は、$needle$haystack内で見つかった場合、0から始まる文字オフセット(整数)を返します。見つからなかった場合はfalseを返します。文字列の先頭で見つかった場合は0を返すため、0falseを厳密に区別するために、比較演算子!==を使用することが重要です。mb_strposを使うことで、マルチバイト文字列の検索を安全かつ正確に行うことができます。

mb_strposは、日本語のようなマルチバイト文字を含む文字列を文字単位で検索します。標準のstrposがバイト単位で処理するため、マルチバイト文字列では期待通りの結果にならないことがあります。「mb_strpos not working」と感じる主な原因はstrposとの混同です。そのため、マルチバイト文字列には必ずmb_strposを使用してください。

この関数は、検索文字列が見つからない場合にfalseを、文字列の先頭で見つかった場合に0を返します。0falseは異なる値ですので、結果の確認は!== falseのように厳密な比較で行ってください。offsetは文字単位で指定します。encoding引数を用いる場合、検索対象と検索文字列のエンコーディングは一致させてください。

PHP mb_strposでUTF-8文字列の位置を検索する

<?php

/**
 * UTF-8文字列内で部分文字列の位置を検索するサンプルコードです。
 * mb_strpos関数はマルチバイト文字(日本語、絵文字など)を正しく扱い、
 * バイト数ではなく文字数で位置を返します。
 * システムエンジニアにとって、特にWebアプリケーション開発で日本語などを扱う際に重要です。
 */
function findStringPositionMb(string $haystack, string $needle, int $offset = 0): void
{
    echo "--- mb_strpos 検索例 ---\n";
    echo "検索対象文字列: '{$haystack}'\n";
    echo "検索する部分文字列: '{$needle}'\n";
    echo "開始オフセット (文字数): {$offset}\n";

    // mb_strpos を使用して、UTF-8エンコーディングで部分文字列を検索します。
    // 見つかった場合は、0から始まる文字位置(バイト位置ではない)を返します。
    // 見つからない場合は false を返します。
    $position = mb_strpos($haystack, $needle, $offset, 'UTF-8');

    if ($position !== false) {
        echo "結果: 部分文字列は {$position} 番目の文字の位置で見つかりました。\n";
    } else {
        echo "結果: 部分文字列は見つかりませんでした。\n";
    }
    echo "-------------------------\n\n";
}

// 実際の使用例

// 1. 基本的な日本語文字列での検索
findStringPositionMb("こんにちは世界!", "世界");

// 2. 開始オフセットを指定した検索 (2文字目から「にち」を検索)
// 「こ」が0文字目、「ん」が1文字目なので、「にち」は2文字目から始まります。
findStringPositionMb("こんにちは世界!", "にち", 1);

// 3. 検索文字列が見つからない場合
findStringPositionMb("Hello World", "PHP");

// 4. オフセットが大きすぎて見つからない場合
// 「世界」は「こんにちは世界!」の4文字目から始まります。
// オフセットを5にすると、検索範囲外になるため見つかりません。
findStringPositionMb("こんにちは世界!", "世界", 5);

// 5. 絵文字を含む文字列での検索 (mb_strposが絵文字も1文字として数えることを示す)
findStringPositionMb("🚀 PHPを学ぼう!", "学ぼう");

// 6. オフセットを指定して絵文字をスキップして検索
// 「🚀」が0文字目なので、「PHP」は2文字目から始まります。
findStringPositionMb("🚀 PHPを学ぼう!", "PHP", 1);

PHPのmb_strpos関数は、UTF-8などのマルチバイト文字列(日本語、絵文字など)において、指定した部分文字列が最初に現れる位置を検索するために利用します。通常のstrpos関数がバイト数を基準とするのに対し、mb_strposはマルチバイト文字を正しく1文字として扱い、バイト数ではなく文字数で位置を返します。システムエンジニアにとって、特にWebアプリケーション開発で日本語などの多様な言語を扱う際に、文字化けや意図しない結果を防ぐために重要な関数です。

この関数は、検索対象の文字列を$haystack、検索する部分文字列を$needle、検索を開始する文字位置を$offset(デフォルトは0)、そして文字列のエンコーディングを$encodingとして受け取ります。通常、$encodingには'UTF-8'を指定します。部分文字列が見つかった場合、戻り値としてその開始位置を0から始まる文字数で返します。例えば「こんにちは」で「こ」は0文字目、「ん」は1文字目となります。部分文字列が見つからなかった場合はfalseを返します。

サンプルコードでは、基本的な日本語文字列での検索や、$offsetを指定して途中から検索する例を示しています。また、検索文字列が見つからない場合や、オフセットが検索範囲を超えて見つからなくなる場合の挙動も確認できます。さらに、絵文字を含む文字列の検索例からは、mb_strposが絵文字も1文字として正確に数えることが分かります。これにより、様々な文字セットを含む文字列操作を正確に行うことが可能です。

mb_strpos関数は、日本語などのマルチバイト文字列を文字数で正確に扱える点が重要です。検索対象が見つからなかった場合、戻り値はfalseとなります。これは0番目の位置と区別する必要があるため、結果を判定する際は$position !== falseのように厳密な比較を必ず使用してください。第三引数のoffsetは、検索を開始するバイト数ではなく文字数で指定します。また、第四引数encodingは対象文字列のエンコーディングを指定します。省略するとPHPの内部エンコーディングが使用されるため、意図しない文字化けや誤った検索結果を防ぐために、'UTF-8'のように明示的に指定することをおすすめします。これにより、堅牢で予測可能なコードになります。

【PHP8.x】mb_strpos関数の使い方 | いっしー@Webエンジニア