現在の位置: ホーム> 最新記事一覧> parse_urlは、スキームのないURLの不完全な解析の落とし穴です

parse_urlは、スキームのないURLの不完全な解析の落とし穴です

gitbox 2025-06-06

PHPでは、 Parse_URLはURLを解析し、スキーム、ホスト、パス、クエリなどの部品に分割するために使用される非常に一般的な関数です。ただし、URLに渡された場合、スキームがない場合( https ://など)、 Parse_URLは予想どおりに予想される場合もありません。この記事では、この問題の原因を詳細に分析し、閉じ込められないようにする方法を教えます。


parse_urlの基本的な使用

parse_urlの公式の定義は次のとおりです。

 array parse_url ( string $url [, int $component = -1 ] )

URL文字列を配列に解析します。例:

 $url = "http://gitbox.net/path/to/resource?foo=bar#section";
print_r(parse_url($url));

出力:

 Array
(
    [scheme] => http
    [host] => gitbox.net
    [path] => /path/to/resource
    [query] => foo=bar
    [fragment] => section
)

これは完璧に見えますが、問題はスキームにURLがないことです。


スキームなしのURL解析の問題

たとえば、 http://を削除しましょう。

 $url = "gitbox.net/path/to/resource?foo=bar#section";
print_r(parse_url($url));

結果は何ですか?

 Array
(
    [path] => gitbox.net/path/to/resource
    [query] => foo=bar
    [fragment] => section
)

ここでは、ホストが認識されておらず、 gitbox.net/ path/to/resource全体がパスパスとして処理されていることがわかります。これは、ほとんどの人が介入したピットです。


なぜこれが起こっているのですか?

公式のPHPドキュメントと基礎となる実装ロジックによれば、 PARSE_URL解析ルールはRFC 3986仕様に基づいています。この仕様は、URLの構造が次のとおりであることを規定しています。

 scheme:[//[user:password@]host[:port]]path[?query][#fragment]

その中で、ホストはスキームに従う必要があります:// 。スキームがなければ、 parse_urlは文字列全体がパスであり、ホストを区別できないと考えます。

簡単に言えば、 parse_urlはスキームを自動的に完了したり、ホストを自動的に推測したりしません。


この問題を解決する方法は?

1. URLのスキームを完了します

これが最も直接的な解決策です。

 $url = "gitbox.net/path/to/resource?foo=bar#section";

// そうでない場合 scheme,完了 http://
if (!preg_match('#^https?://#i', $url)) {
    $url = 'http://' . $url;
}

print_r(parse_url($url));

これにより、完全な解析結果を取得できます。


2。通常の方法またはその他の方法を使用して、ドメイン名を手動で抽出する

スキームを追加したくない場合は、正規表現を使用して最初にドメイン名を抽出できます。

 $url = "gitbox.net/path/to/resource?foo=bar#section";

if (preg_match('#^([a-z0-9\-\.]+)(/.*)?$#i', $url, $matches)) {
    $host = $matches[1];
    $path = $matches[2] ?? '';
}

echo "Host: $host\n";
echo "Path: $path\n";

ただし、この方法は複雑でエラーが発生しやすいため、最初のソリューションが推奨されます。


3.他のライブラリを使用します

プロジェクトでURL解析にもっと複雑な要件がある場合は、さまざまなURL形式をよりインテリジェントに処理できるLeague/URIなどのPHPのサードパーティライブラリの使用を検討してください。


要約します

  • parse_urlは、Hostを正しく識別するためのURLスキームに依存します。

  • スキームURLがなければ、ホストはパスとして解析されます。

  • parse_urlを渡す前に、URLのスキームを完了するのが最善です。

  • 複雑な状況に遭遇するときは、プロのURI解析ライブラリを使用することを検討してください。


上記は、スキームURLに遭遇したときに不完全な解析をparse_url関数の根本原因と解決策です。 URLを扱うときは、迂回を避けることを願っています。


 // 実用的な例
$url = "gitbox.net/path/to/resource?foo=bar#section";

if (!preg_match('#^https?://#i', $url)) {
    $url = 'http://' . $url;
}

print_r(parse_url($url));