PHP URI: получение текущего адреса строки запроса
Получение URI в PHP: основные подходы
Основной способ получения текущего URI
Наиболее надёжным методом является использование суперглобального массива $_SERVER['REQUEST_URI']. Он содержит путь запроса вместе с query-строкой (если она есть). Однако значение может быть неэкранированным и содержать потенциально опасные символы, поэтому его нужно обрабатывать.
$uri = $_SERVER['REQUEST_URI'] ?? '/';
$uri = filter_var($uri, FILTER_SANITIZE_URL);
$parts = parse_url($uri);Php проверить ссылку (проверить ссылку в php)
После этого можно получить отдельные компоненты: путь ($parts['path']), query ($parts['query']), фрагмент ($parts['fragment']).
Проблема: XSS через неэкранированный URI
Если выводить URI или его части в HTML без экранирования, возможна межсайтовая атака. Решение - всегда применять htmlspecialchars() перед выводом.
Как получить URI без query-параметров?
Иногда нужен только путь (без GET-параметров). Можно использовать strtok() или parse_url() с флагом PHP_URL_PATH:
$path = strtok($_SERVER['REQUEST_URI'], '?');
// или
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);Id ссылки php (идентификатор ссылки в php)
Проблема: пустой path при корне
Если запрос идёт к корню (/), parse_url вернёт пустую строку. Рекомендуется использовать условие $path = $path ?: '/';.
Как составить полный URI (схема, хост, порт)?
$_SERVER['REQUEST_URI'] содержит только путь. Для сборки абсолютного URI нужно добавить протокол, домен и порт. Пример:
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$port = $_SERVER['SERVER_PORT'];
$uri = $_SERVER['REQUEST_URI'];
$fullUri = $protocol . '://' . $host . ($port != 80 && $port != 443 ? ':' . $port : '') . $uri;
активная ссылка php (создание активной ссылки в php)
Проблема: неверный порт при reverse proxy
За балансировщиком нагрузки или прокси реальный порт может быть передан через заголовок X-Forwarded-For или X-Forwarded-Port. Для точности нужно обрабатывать эти заголовки, но с осторожностью (доверять только из внутренней сети).
Как получить URI в консольном скрипте (CLI)?
Для скриптов командной строки суперглобальные переменные HTTP-запроса отсутствуют. URI можно передать как аргумент:
// php script.php /some/path?foo=bar
$uri = $argv[1] ?? '/';
// или использовать getopt() для более сложной обработкиPhp ссылки (работа с url и ссылками в php)
Проблема: отсутствие стандарта
Нет единого способа - все зависит от соглашений в проекте. Рекомендуется задокументировать ожидаемый формат.
Как обработать URI при rewrite (nginx, Apache)?
После rewrite $_SERVER['REQUEST_URI'] может содержать изменённый путь, а исходный - $_SERVER['REDIRECT_URL'] или $_SERVER['ORIGINAL_PATH_INFO'] (в Apache). Пример проверки:
$uri = $_SERVER['REQUEST_URI'];
if (isset($_SERVER['REDIRECT_URL'])) {
$uri = $_SERVER['REDIRECT_URL'];
}
Проблема: неполная совместимость
Ключи массивов зависят от конфигурации веб-сервера. Для портируемости лучше использовать $_SERVER['REQUEST_URI'] как единую точку входа.
Расширенные примеры работы с URI в PHP:
Пример 1. Извлечение домена из URI
$fullUri = 'https://user:pass@example.com:8080/path?query=val#frag';
$components = parse_url($fullUri);
echo $components['host']; // example.com
echo $components['scheme']; // https
echo $components['port']; // 8080
example.com https 8080
Пояснение: parse_url разбирает абсолютный URI на части. Для относительных URI схема и хост будут отсутствовать.
Пример 2. Сборка URI из компонентов
$parts = [
'scheme' => 'https',
'host' => 'example.com',
'path' => '/api/v1/resource',
'query' => 'id=42&limit=10',
'fragment' => 'section1'
];
$uri = http_build_url($parts); // требует PECL extension 'http'
// или ручная сборка:
$uri = $parts['scheme'] . '://' . $parts['host'] . $parts['path'];
$uri .= '?' . $parts['query'];
$uri .= '#' . $parts['fragment'];
echo $uri;
https://example.com/api/v1/resource?id=42&limit=10#section1
Пояснение: ручная сборка полезна при отсутствии расширения. Важно правильно закодировать query-строку с помощью http_build_query().
Пример 3. Обработка URI в многобайтовых кодировках
// URI может содержать не ASCII символы (например, кириллица)
$uri = '/%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80?name=%D0%98%D0%B2%D0%B0%D0%BD';
$decodedUri = rawurldecode($uri);
echo $decodedUri; // /пример?name=Иван
// Для безопасного вывода:
echo htmlspecialchars($decodedUri, ENT_QUOTES, 'UTF-8');
/пример?name=Иван
Пояснение: rawurldecode корректно раскодирует процентную последовательность. Отличие от urldecode - не интерпретирует '+' как пробел, что правильно для пути.
Пример 4. Получение URI из внешнего запроса (cURL)
$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$response = curl_exec($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
// Извлечение URI перенаправления:
preg_match('/^Location: (.+)$/im', $header, $matches);
$redirectUri = $matches[1] ?? null;
echo $redirectUri;
curl_close($ch);
https://api.example.com/redirected
Пояснение: при выполнении внутренних HTTP-запросов часто нужно извлечь URI из ответа, например, для обработки редиректов.
Пример 5. Использование filter_var для валидации URI
$userInput = 'http://example.com/path with spaces';
$sanitized = filter_var($userInput, FILTER_SANITIZE_URL);
echo $sanitized; // http://example.com/path%20with%20spaces
$valid = filter_var($sanitized, FILTER_VALIDATE_URL);
var_dump($valid); // false, потому что нет query? - на самом деле валидный
http://example.com/path%20with%20spaces bool(false)
Пояснение: FILTER_VALIDATE_URL довольно строгий - не пропускает относительные пути и требует схему. Для проверки локальных URI лучше использовать parse_url() и собственную логику.
Пример 6. Работа с фрагментом (#) на клиенте
// Фрагменты не передаются на сервер в HTTP-запросе
// Но можно получить их через JavaScript и отправить через Ajax
// В PHP для входящих запросов $_SERVER['REQUEST_URI'] не содержит #
$uri = $_SERVER['REQUEST_URI'];
echo preg_replace('/#.*/', '', $uri); // удаление фрагмента, если каким-то образом попал
Пояснение: фрагмент обрабатывается только браузером, поэтому серверный код не может его получить стандартными средствами.