Получение текущего URL в PHP: от простого к сложному
Способы получения текущего URL в PHP
Основное универсальное решение
Функция getCurrentUrl() собирает полный URL с учётом протокола, домена, порта, пути и строки запроса.
function getCurrentUrl(): string {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
if (isset($_SERVER['REQUEST_SCHEME'])) {
$scheme = $_SERVER['REQUEST_SCHEME'];
}
$host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';
$port = '';
if (isset($_SERVER['SERVER_PORT']) &&
(($scheme === 'http' && $_SERVER['SERVER_PORT'] != 80) ||
($scheme === 'https' && $_SERVER['SERVER_PORT'] != 443))) {
$port = ':' . $_SERVER['SERVER_PORT'];
}
$uri = $_SERVER['REQUEST_URI'] ?? '/';
return $scheme . '://' . $host . $port . $uri;
}Php создание ссылки (создание ссылки в php)
Пошаговое объяснение:
1. Определяем протокол через переменную $_SERVER['HTTPS']. Если она не пуста и не равна 'off' – значит HTTPS.
2. Используем $_SERVER['REQUEST_SCHEME'] как альтернативный источник (доступен в Apache 2.4+).
3. Берём домен из HTTP_HOST (включает порт), но если его нет – из SERVER_NAME.
4. Порт добавляем только если он нестандартный (80 для HTTP, 443 для HTTPS).
5. Путь с query-строкой берётся из REQUEST_URI.
6. Собираем итоговую строку.
Возможные проблемы и их решения:
- Переменная
$_SERVER['HTTPS']может отсутствовать (например, в некоторых конфигурациях FastCGI). Решение: проверить её черезisset(). - За прокси-сервером настоящий протокол может быть передан в заголовке
X-Forwarded-Proto. Тогда нужно проверять$_SERVER['HTTP_X_FORWARDED_PROTO'], но это требует доверия к прокси. - Значение
HTTP_HOSTможет содержать порт (например, example.com:8080). Если порт уже включён, его не следует дублировать. В решении выше порт отделяется, поэтому нужно либо разбиратьHTTP_HOST, либо использоватьSERVER_NAME. В примере использованHTTP_HOSTкак есть; если требуется убрать порт из хоста, нужно применитьparse_url($host, PHP_URL_HOST).
Как получить только путь и строку запроса (без протокола и домена)?
$currentPath = $_SERVER['REQUEST_URI'];
echo $currentPath; // например: /blog/article?id=10Php текущая url (текущая url в php)
Проблемы:
- При использовании внутренних редиректов (например, при перезаписи в .htaccess)
REQUEST_URIможет содержать исходный запрос, а не конечный файл. Для получения физического пути используйте$_SERVER['SCRIPT_NAME']. - Если страница доступна через несколько маршрутов, значение может отличаться.
Как получить полный URL без строки запроса?
$urlWithoutQuery = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' .
$_SERVER['HTTP_HOST'] . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
echo $urlWithoutQuery; // https://example.com/blog/articleMobile php url (мобильный url в php)
Особенности:
- Функция
parse_url()корректно отсекает query. Если в пути есть фрагмент (#), он тоже отбрасывается. - При отсутсвии query вернётся тот же путь.
Как получить текущий URL в условиях работы за балансировщиком нагрузки?
function getCurrentUrlBehindProxy(): string {
$scheme = 'http';
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
$scheme = $_SERVER['HTTP_X_FORWARDED_PROTO'];
} elseif (!empty($_SERVER['HTTPS'])) {
$scheme = 'https';
}
$host = $_SERVER['HTTP_X_FORWARDED_HOST'] ?? $_SERVER['HTTP_HOST'] ?? 'localhost';
$uri = $_SERVER['REQUEST_URI'] ?? '/';
return $scheme . '://' . $host . $uri;
}Php open url (открытие url в php)
Риски:
- Заголовки
X-Forwarded-*могут быть подделаны клиентом. Используйте только если сервер доверяет прокси (настройкаTrustedProxiesв фреймворках). - Не все прокси передают порт отдельно. В таком случае порт может содержаться в
HTTP_HOST.
Как получить URL, гарантированно совпадающий с тем, что видит пользователь (с учётом rewrite)?
// Использование $_SERVER['SCRIPT_URI'] (доступен в некоторых серверных API)
if (isset($_SERVER['SCRIPT_URI'])) {
$url = $_SERVER['SCRIPT_URI']; // полный URL от сервера
} else {
$url = getCurrentUrl();
}Js php url (javascript и php url)
Замечание:
$_SERVER['SCRIPT_URI']генерируется сервером на основе фактических директив, но не всегда присутствует (отсутствует в IIS, некоторых конфигурациях Apache).- Не получить использовать во всех окружениях.
Как безопасно получить URL для вывода на странице или в логе?
$currentUrl = filter_var(getCurrentUrl(), FILTER_SANITIZE_URL);
echo htmlspecialchars($currentUrl, ENT_QUOTES, 'UTF-8');Безопасность:
- Выводить URL без санитизации может привести к XSS-атакам, если злоумышленник передаёт вредоносные параметры.
- Функция
filter_var(..., FILTER_SANITIZE_URL)удаляет запрещённые символы, но не гарантирует безопасность при выводе. Всегда применяйтеhtmlspecialchars.
Дополнительные расширенные примеры работы с текущим URL
Пример 1: Извлечение компонентов URL с помощью regex
$url = getCurrentUrl();
// Извлекаем протокол, домен, порт, путь и query
preg_match('|^(https?://[^/]+)(?::(\d+))?(/.*?)(\?.*)?$|i', $url, $matches);
$components = [
'base' => $matches[1],
'port' => $matches[2] ?? '',
'path' => $matches[3],
'query' => $matches[4] ?? ''
];
print_r($components);Array
(
[base] => https://example.com
[port] =>
[path] => /blog/article
[query] => ?id=10
)Этот подход даёт больше контроля, но избыточен по сравнению с parse_url(). Используется, когда необходимы нестандартные обработки (например, проверка на определённые паттерны).
Пример 2: Получение URL для CLI-скрипта (имитация веб-окружения)
// В командной строке $_SERVER отсутствует. Моделируем:
if (php_sapi_name() === 'cli') {
$currentUrl = 'http://localhost' . ($argv[1] ?? '/');
echo "URL (имитация): $currentUrl\n";
} else {
echo "Веб-запрос, реальный URL: " . getCurrentUrl();
}URL (имитация): http://localhost/test?param=1
Позволяет тестировать функции, работающие с URL, в консоли. Первым аргументом передаётся путь.
Пример 3: Сравнение производительности методов (micro-бенчмарк)
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$url = 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}
$end = microtime(true);
echo "Сборка строкой: " . ($end - $start) . " сек.\n";
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$url = sprintf('%s://%s%s',
(!empty($_SERVER['HTTPS']) ? 'https' : 'http'),
$_SERVER['HTTP_HOST'],
$_SERVER['REQUEST_URI']
);
}
$end = microtime(true);
echo "sprintf: " . ($end - $start) . " сек.\n";Сборка строкой: 0.042 сек. sprintf: 0.039 сек.
Разница незначительная, но sprintf может быть читаемее. Для высоких нагрузок обычно не критично.
Пример 4: Обработка ситуации, когда сервер передаёт порт в HTTP_HOST (случай нестандартного порта)
$rawHost = $_SERVER['HTTP_HOST']; // например, example.com:8080
$parts = parse_url('http://' . $rawHost); // протокол не важен
$host = $parts['host'];
$port = isset($parts['port']) ? ':' . $parts['port'] : '';
$scheme = (!empty($_SERVER['HTTPS'])) ? 'https' : 'http';
$fullUrl = $scheme . '://' . $host . $port . $_SERVER['REQUEST_URI'];
echo $fullUrl;http://example.com:8080/path?q=1
Важно, чтобы не было дублирования порта, если он уже в REQUEST_URI (редко).
Пример 5: Использование констант и переменных окружения для совместимости
// Некоторые CMS хранят базовый URL в конфигурации
define('BASE_URL', 'https://mysite.com');
// Функция получает относительный путь от корня домена
function getFullUrlRelative(): string {
$base = BASE_URL;
return $base . $_SERVER['REQUEST_URI'];
}
echo getFullUrlRelative();https://mysite.com/blog/article?id=10
Подходит, когда домен фиксирован, нет необходимости динамически определять протокол. Минус - при смене домена или протокола придётся менять константу.
Пример 6: Получение URL с поддержкой альтернативных серверов (IIS, nginx)
if (isset($_SERVER['IIS_WasUrlRewritten'])) {
// В IIS с включённой Rewrite может быть другая переменная
$uri = $_SERVER['UNENCODED_URL'] ?? $_SERVER['REQUEST_URI'];
} else {
$uri = $_SERVER['REQUEST_URI'];
}
$scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
echo $scheme . '://' . $host . $uri;Этот код проверяет наличие специфичных серверных переменных, что повышает переносимость.
Пример 7: Извлечение query-параметров из текущего URL и их изменение
$url = getCurrentUrl();
$parsed = parse_url($url);
parse_str($parsed['query'] ?? '', $queryParams);
$queryParams['page'] = 2; // изменить параметр
$newQuery = http_build_query($queryParams);
$newUrl = $parsed['scheme'] . '://' . $parsed['host'] . $parsed['path'] . '?' . $newQuery;
echo $newUrl;https://example.com/list?page=2&filter=active
Позволяет перестраивать URL с новыми параметрами, сохраняя порядок и кодировку.