Информация о URL в PHP: как получить и обработать адрес страницы
Основные подходы к получению и разбору URL
Как получить текущий URL страницы в PHP?
Наиболее эффективное решение основывается на суперглобальном массиве $_SERVER. Для полного URL (включая протокол, хост, порт, путь и строку запроса) используется комбинация элементов:
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443 ? 'https://' : 'http://';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$uri = $_SERVER['REQUEST_URI'] ?? '/';
$fullUrl = $protocol . $host . $uri;
echo $fullUrl;
Пояснение: $_SERVER['HTTPS'] определяет, работает ли соединение по HTTPS. Если сервер не передаёт эту переменную, проверяется порт 443. $_SERVER['HTTP_HOST'] содержит домен и порт (если нестандартный). $_SERVER['REQUEST_URI'] возвращает путь и строку запроса.
Проблема: на некоторых серверах (например, при использовании CLI) массив $_SERVER может не содержать нужных ключей. Решение - использовать filter_input(INPUT_SERVER, '...') с проверкой на null.
Как разобрать URL на составные части?
Функция parse_url() разбивает URL на ассоциативный массив: scheme, host, port, user, pass, path, query, fragment. Пример:
$url = 'https://user:pass@example.com:8080/path/to/page?name=value&key=value#anchor';
$parts = parse_url($url);
print_r($parts);
Array
(
[scheme] => https
[host] => example.com
[port] => 8080
[user] => user
[pass] => pass
[path] => /path/to/page
[query] => name=value&key=value
[fragment] => anchor
)
Цель: извлечение отдельных компонентов для дальнейшей обработки, например, для определения домена или пути.
Ошибка: если URL содержит кириллицу или специальные символы, parse_url может вернуть некорректные или пустые значения. Решение - предварительно закодировать строку через urlencode() или использовать rawurlencode() только для отдельных частей.
Как получить параметры запроса из URL?
Для извлечения GET-параметров используется parse_str(). Она преобразует строку запроса в ассоциативный массив:
$queryString = $_SERVER['QUERY_STRING'] ?? '';
parse_str($queryString, $params);
print_r($params);
Если нужно разобрать произвольный URL, предварительно получают query через parse_url($url, PHP_URL_QUERY).
Проблема: если в параметрах встречаются символы, не прошедшие URL-кодирование (например, пробелы), parse_str может обработать их некорректно. Решение: перед парсингом применить urldecode() ко всей строке или к каждому значению.
Как собрать URL из частей?
Функция http_build_query() создаёт строку запроса из массива. Полный URL собирается конкатенацией:
$scheme = 'https';
$host = 'example.com';
$path = '/search';
$params = ['q' => 'PHP URL', 'page' => 2];
$query = http_build_query($params);
$url = $scheme . '://' . $host . $path . '?' . $query;
echo $url;
https://example.com/search?q=PHP+URL&page=2
Цель: динамическое создание ссылок, корректное экранирование параметров.
Типичная ошибка: использование неэкранированных символов вручную. http_build_query автоматически кодирует ключи и значения, но если нужно изменить разделитель (например, на &), используется второй аргумент.
Как кодировать и декодировать URL?
PHP предоставляет urlencode() (пробел заменяется на +) и rawurlencode() (пробел на %20). Первый применяется для application/x-www-form-urlencoded, второй - для RFC 3986. Пример:
$original = 'Hello World!';
echo urlencode($original) . "\n";
echo rawurlencode($original);
Hello+World%21 Hello%20World%21
Декодирование: urldecode() и rawurldecode().
Ошибка: двойное кодирование. Если закодированную строку повторно пропустить через urlencode, символ % станет %25. Решение - проверять, не является ли строка уже закодированной, или использовать единый подход.
Как проверить, что URL является действительным?
Фильтр FILTER_VALIDATE_URL проверяет синтаксис URL:
$url = 'https://example.com';
if (filter_var($url, FILTER_VALIDATE_URL)) {
echo 'URL валиден';
} else {
echo 'URL невалиден';
}
Цель: проверка пользовательского ввода на корректность.
Недостаток: фильтр не проверяет существование домена, а только синтаксис. Для дополнительной проверки используйте checkdnsrr() или попытку подключения через cURL.
Расширенные примеры работы с URL в PHP
Пример 1. Получение полного URL с учётом протокола, порта и пользовательской части
Следующий код собирает полный URL из всех доступных серверных переменных:
function getFullUrl() {
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$port = $_SERVER['SERVER_PORT'] ?? 80;
$path = $_SERVER['REQUEST_URI'] ?? '/';
$user = $_SERVER['PHP_AUTH_USER'] ?? '';
$pass = $_SERVER['PHP_AUTH_PW'] ?? '';
$auth = '';
if ($user) {
$auth = rawurlencode($user) . ':' . rawurlencode($pass) . '@';
}
if (($protocol === 'http' && $port != 80) || ($protocol === 'https' && $port != 443)) {
$host = $host; // порт уже может быть в HTTP_HOST
} else {
$port = '';
}
return $protocol . '://' . $auth . $host . ($port ? ':' . $port : '') . $path;
}
echo getFullUrl();
https://user:pass@example.com:8080/path?arg=value
Пример 2. Разбор URL с последующим кодированием кириллических параметров
Допустим, URL содержит русские буквы в пути или запросе. Сначала разбираем, затем кодируем:
$rawUrl = 'https://пример.рф/путь?имя=значение';
$encodedPath = rawurlencode(parse_url($rawUrl, PHP_URL_PATH)); // %D0%BF%D1%83%D1%82%D1%8C
$query = parse_url($rawUrl, PHP_URL_QUERY);
parse_str($query, $params);
$encodedQuery = http_build_query($params, '', '&');
$finalUrl = 'https://xn--e1afmkfd.xn--p1ai/' . ltrim($encodedPath, '/') . '?' . $encodedQuery;
echo $finalUrl;
https://xn--e1afmkfd.xn--p1ai/%D0%BF%D1%83%D1%82%D1%8C?%D0%B8%D0%BC%D1%8F=%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5
Пример 3. Сборка URL с якорем (фрагментом) через http_build_query
В URL якорь добавляется после #. http_build_query не обрабатывает фрагменты, поэтому его добавляют вручную:
$base = 'https://example.com/page';
$params = ['id' => 123, 'section' => 'faq'];
$query = http_build_query($params);
$fragment = 'section2';
$url = $base . '?' . $query . '#' . $fragment;
echo $url;
https://example.com/page?id=123§ion=faq#section2
Пример 4. Извлечение домена и поддоменов с помощью parse_url
Для анализа структуры хоста:
$url = 'https://subdomain.example.co.uk/page';
$host = parse_url($url, PHP_URL_HOST); // subdomain.example.co.uk
$parts = explode('.', $host);
if (count($parts) >= 2) {
$domain = $parts[count($parts)-2] . '.' . $parts[count($parts)-1];
$subdomain = implode('.', array_slice($parts, 0, count($parts)-2));
echo "Домен: $domain\n";
echo "Поддомен: $subdomain\n";
}
Домен: example.co.uk Поддомен: subdomain
Пример 5. Валидация URL с проверкой DNS
Комбинированная проверка синтаксиса и существования домена:
function validateUrl($url) {
if (!filter_var($url, FILTER_VALIDATE_URL)) {
return false;
}
$host = parse_url($url, PHP_URL_HOST);
if (!$host) return false;
return checkdnsrr($host, 'A') || checkdnsrr($host, 'AAAA');
}
$testUrl = 'https://google.com';
if (validateUrl($testUrl)) {
echo 'URL корректен и домен существует';
} else {
echo 'URL некорректен или домен не найден';
}
URL корректен и домен существует