Как получить полный URL текущей страницы в PHP?
Правильное получение полного URL в PHP
Ваша задача — классическая ситуация, с которой сталкивается почти каждый PHP-разработчик. Главная сложность в том, что $_SERVER — это суперглобальный массив, содержимое которого сильно зависит от конфигурации веб-сервера. Вот надёжное решение, которое учитывает все основные случаи.
Универсальная функция
function getFullUrl() {
// Определяем протокол
$protocol = 'http';
if (
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ||
(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) ||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
) {
$protocol = 'https';
}
// Получаем хост (домен)
$host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';
// Получаем URI (путь + GET параметры)
$uri = $_SERVER['REQUEST_URI'] ?? '/';
// Собираем полный URL
return $protocol . '://' . $host . $uri;
}
Пояснение ключевых моментов
- Протокол: проверяем три варианта — стандартный
HTTPS, порт 443 (часто используется при reverse proxy) и заголовокX-Forwarded-Proto(для балансировщиков нагрузки). - Хост: используем
HTTP_HOST(он включает порт, если он нестандартный), если его нет —SERVER_NAME, в крайнем случае —localhost. - URI:
REQUEST_URIсодержит всё, что идёт после домена, включая GET-параметры и якоря (#).
Дополнительные варианты
Если вам нужен URL без GET-параметров (только путь):
$urlWithoutQuery = strtok(getFullUrl(), '?');
Если нужен только базовый URL (протокол + домен):
function getBaseUrl() {
$protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
return $protocol . '://' . $host;
}
Важные замечания
- Функция
getFullUrl()работает корректно на 99% серверов, включая Apache, Nginx и OpenServer. - Для CLI-скриптов (запуск из командной строки)
$_SERVERможет быть пустым — в таких случаях функция вернётhttp://localhost/. - Если ваш сайт работает за reverse proxy (например, Cloudflare или Nginx как прокси), обязательно проверяйте заголовок
X-Forwarded-Proto— иначе вы всегда будете получатьhttp, даже если реальное соединение HTTPS.
Используйте эту функцию в вашем логгере — она надёжна, проста и покрывает 99% реальных сценариев.
<<Альтернативный подход: использование фильтров и обработка ошибок
Если вам нужно не просто получить URL, но и проверить его валидность, можно использовать комбинацию filter_var и запасных значений:
function safeGetFullUrl() {
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = filter_input(INPUT_SERVER, 'HTTP_HOST', FILTER_SANITIZE_URL) ?: 'localhost';
$uri = filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL) ?: '/';
$url = $protocol . '://' . $host . $uri;
// Проверка валидности URL
if (filter_var($url, FILTER_VALIDATE_URL) === false) {
// Запасной вариант — собираем вручную
$url = $protocol . '://' . $host . '/' . ltrim($uri, '/');
}
return $url;
}
Плюсы этого подхода:
- Безопаснее — использует
filter_inputвместо прямого доступа к массиву, что защищает от XSS-атак. - Валидация — проверяет, что получился корректный URL.
- Обработка ошибок — если что-то пошло не так, функция всё равно вернёт рабочий URL.
Этот вариант особенно полезен, если вы выводите URL на страницу (например, в мета-теги) и хотите избежать инъекций.