PHP에서 Parse_url은 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이 없다는 것입니다.
예를 들어 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/toto/resource 가 경로 경로 로 처리됩니다. 이것은 대부분의 사람들이 밟은 구덩이입니다.
공식 PHP 문서 및 기본 구현 로직에 따르면 Parse_url 구문 분석 규칙은 RFC 3986 사양을 기반으로합니다. 이 사양은 URL의 구조가 다음과 같습니다.
scheme:[//[user:password@]host[:port]]path[?query][#fragment]
그중에서도 호스트는 다음을 따라야합니다 : // . 체계가 없으면 Parse_url은 전체 문자열이 경로이며 호스트를 구별 할 수 없다고 생각합니다.
간단히 말해서, parse_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));
이렇게하면 완전한 구문 분석 결과를 얻을 수 있습니다.
체계를 추가하지 않으려면 정규 표현식을 사용하여 도메인 이름을 먼저 추출 할 수 있습니다.
$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";
그러나이 방법은 복잡하고 오류가 발생하기 쉬우므로 첫 번째 솔루션을 권장합니다.
프로젝트에 URL 구문 분석에 대한 더 복잡한 요구 사항이있는 경우 PHP의 타사 라이브러리와 같은 리그/URI 와 같은 다양한 URL 형식을보다 지능적으로 처리 할 수 있습니다.
parse_url은 호스트를 올바르게 식별하기 위해 URL 구성표에 따라 다릅니다.
체계 URL이 없으면 호스트는 경로로 구문 분석됩니다.
parse_url을 통과하기 전에 URL의 체계를 완료하는 것이 가장 좋습니다.
복잡한 상황이 발생할 때 전문 URI 구문 분석 라이브러리 사용을 고려하십시오.
위는 Parse_url 함수가 체계 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));