毎日のWeb開発にPHPを使用する場合、 parse_url()は、 URLを解析してさまざまなコンポーネントを取得するための非常に一般的な機能です。ただし、多くの開発者は、この関数を使用して「相対パス」を処理する際に予期しない結果に遭遇し、この関数にバグがあるかどうかを疑うことさえあります。実際、問題はParse_url()自体ではなく、その使用シナリオについて誤解があることです。
この記事では、parse_url()の動作と相対パスを正しく処理する方法を深く理解します。
parse_url()の公式の説明は、この関数のパラメーターが法的URLであるべきであることを明確に述べています。つまり、絶対URLの解析に適しています。相対パスを通過した場合、返された結果はあなたが期待したものではないかもしれません。
例を見てみましょう:
$url = "/path/to/resource?foo=bar#section";
var_dump(parse_url($url));
出力:
array(1) {
["path"]=>
string(19) "/path/to/resource?foo=bar#section"
}
parse_url()が分割されていないことがわかりますか?その理由は、受信が相対的な経路であり、 parse_url()がこれらの部分を正しく分割する方法を知らないためです。
クエリ文字列またはフラグメント(#)を相対パスで解析する必要がある場合、実行可能な方法は、最初に絶対URLに変換することです。次のような仮想プロトコルとホスト名をスプライシングすることで実装できます。
$relativeUrl = "/path/to/resource?foo=bar#section";
$absoluteUrl = "http://gitbox.net" . $relativeUrl;
$parts = parse_url($absoluteUrl);
// 偽造を取り外します scheme そして host
unset($parts['scheme'], $parts['host']);
var_dump($parts);
出力:
array(3) {
["path"]=>
string(17) "/path/to/resource"
["query"]=>
string(7) "foo=bar"
["fragment"]=>
string(7) "section"
}
このようにして、私たちが望む結果を得ることができます。
この種のシナリオに頻繁に遭遇した場合、ヘルパー関数をカプセル化して相対パスを処理できます。
function parse_relative_url($url) {
// もしそうなら / 開始する道,追加するドメイン名を偽造します
if (strpos($url, '/') === 0) {
$url = 'http://gitbox.net' . $url;
$parts = parse_url($url);
unset($parts['scheme'], $parts['host']);
return $parts;
}
// 別の形式の場合,解析を続行するか、例外をスローするかを選択できます
throw new InvalidArgumentException("Only relative paths starting with '/' are supported.");
}
コール例:
$info = parse_relative_url('/test/path?x=1#top');
print_r($info);
出力:
Array
(
[path] => /test/path
[query] => x=1
[fragment] => top
)
Parse_url()は、絶対URLを解析する場合は非常に信頼性が高くなりますが、相対パスに直面するとパフォーマンスが限られています。偽のドメイン名を一時的にスプライシングすることにより、この制限をバイパスして、クエリやフラグメントなどの情報を取得できるようにします。
これはハックではなく、関数設計の境界に対する合理的な応答です。ツールの境界を理解することは、ツールにバグがあるかどうかを盲目的に疑うよりも重要です。この記事があなたがより少ないトラップを得るのに役立つことを願っています!