Способы определения адреса в PHP: от простого URL до IP клиента
Основные способы получения адреса в PHP
Как получить полный URL текущей страницы?
Наиболее эффективное решение - собрать URL из компонентов суперглобального массива $_SERVER. Это даёт протокол, домен, порт, путь и query-строку. Подходит для большинства веб-серверов (Apache, Nginx) и не требует дополнительных расширений.
<?php
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'];
$uri = $_SERVER['REQUEST_URI'];
$fullUrl = $protocol . '://' . $host . $uri;
echo $fullUrl;
?>
Php получить куки (получение куки в php)
Пояснение шагов:
- Проверяется наличие HTTPS через ключ
HTTPS- если он равен 'on' или не равен 'off', схема 'https'. HTTP_HOSTсодержит домен с портом (если нестандартный). Если его нет, берётсяSERVER_NAME.REQUEST_URI- путь и query-строка (например,/page?id=1).
Возможные проблемы и их решения:
- Проблема: на некоторых конфигурациях
REQUEST_URIможет отсутствовать (редко, в старых CGI-версиях).
Решение: использовать$_SERVER['SCRIPT_NAME']+$_SERVER['QUERY_STRING']. - Проблема: при работе через CLI (консоль) массив
$_SERVERпочти пуст.
Решение: проверять наличие ключей или задавать значения по умолчанию. - Проблема: значение
HTTP_HOSTможет быть подменено в HTTP-заголовке Host (уязвимость Host header injection).
Решение: при необходимости проверять его через белый список доменов.
Цели использования: построение абсолютных ссылок, редиректы, логирование, формирование canonical URL.
Как получить только путь и query-строку без домена?
<?php
$relativeUrl = $_SERVER['REQUEST_URI'];
echo $relativeUrl;
?>
Php получить html (получение html-кода в php)
Используется, когда нужна относительная часть URL - например, для анализа текущего маршрута в роутере.
На серверах с rewrite может отличаться значение от фактического URL. Проверять через $_SERVER['ORIG_PATH_INFO'].
Как получить базовый URL (схема + хост) без пути?
<?php
$baseUrl = $protocol . '://' . $host;
echo $baseUrl;
?>
Php получить заголовок (получение заголовка в php)
Полезно для формирования ссылок на корень сайта или API-эндпоинты.
Как получить IP-адрес клиента?
<?php
$ip = $_SERVER['REMOTE_ADDR'];
echo $ip;
?>
Php получить json (получение json в php)
Стандартный способ, но не учитывает прокси-серверы. Если сайт за CloudFlare или балансировщиком, реальный адрес может быть в заголовках X-Forwarded-For или X-Real-IP.
Использовать заголовки напрямую опасно - клиент может подделать. Рекомендуется доверять только проверенным прокси (например, через список доверенных IP).
Как получить IP-адрес сервера?
<?php
echo $_SERVER['SERVER_ADDR'];
?>
Php получить адрес (получение адреса в php)
Может пригодиться для определения, на каком интерфейсе выполняется скрипт (например, в многодоменной среде).
Как получить порт, если он отличается от стандартного?
<?php
$port = $_SERVER['SERVER_PORT'];
echo $port;
?>
Значение порта доступно через SERVER_PORT. Если порт 80 или 443, его обычно не включают в URL, но можно добавить при необходимости.
Расширенные примеры получения адреса
Полный URL с учётом нестандартного порта и HTTPS через proxy
<?php
function getCurrentUrl(): string
{
$protocol = 'http';
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
$protocol = 'https';
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
// Заголовок от прокси (например, CloudFlare)
$protocol = 'https';
}
$host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'];
$port = $_SERVER['SERVER_PORT'];
// Исключаем стандартные порты
if (($protocol === 'http' && $port === '80') || ($protocol === 'https' && $port === '443')) {
$portPart = '';
} else {
$portPart = ':' . $port;
}
$uri = $_SERVER['REQUEST_URI'];
return $protocol . '://' . $host . $portPart . $uri;
}
echo getCurrentUrl();
?>
https://example.com:8443/page?q=test
Пример учитывает прокси-заголовок X-Forwarded-Proto и подавляет стандартные порты.
Разбор URL на компоненты с помощью parse_url
<?php
$url = 'https://user:pass@example.com:8080/path?arg=1#fragment';
$parts = parse_url($url);
print_r($parts);
?>
Array
(
[scheme] => https
[host] => example.com
[port] => 8080
[user] => user
[pass] => pass
[path] => /path
[query] => arg=1
[fragment] => fragment
)
parse_url удобен для извлечения отдельных частей URL, особенно при работе со ссылками из внешних источников.
Получение IP-адреса клиента с учётом доверенных прокси
<?php
function getClientIp(array $trustedProxies = []): string
{
if (!empty($trustedProxies) && in_array($_SERVER['REMOTE_ADDR'], $trustedProxies, true)) {
// Если запрос пришёл от доверенного прокси, проверяем заголовки
$forwardedFor = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
if ($forwardedFor !== '') {
// Берём первый IP из цепочки (самый близкий к клиенту)
$ips = explode(',', $forwardedFor);
return trim($ips[0]);
}
$realIp = $_SERVER['HTTP_X_REAL_IP'] ?? '';
if ($realIp !== '') {
return $realIp;
}
}
return $_SERVER['REMOTE_ADDR'];
}
$trusted = ['10.0.0.1', '203.0.113.5']; // IP ваших балансировщиков
echo getClientIp($trusted);
?>
Этот код гарантирует, что заголовки используются только от доверенных прокси, предотвращая подделку IP.
Получение серверного адреса и имени хоста
<?php
echo 'IP сервера: ' . $_SERVER['SERVER_ADDR'] . PHP_EOL;
echo 'Имя сервера: ' . $_SERVER['SERVER_NAME'] . PHP_EOL;
// Альтернатива: gethostname()
echo 'Сетевое имя: ' . gethostname() . PHP_EOL;
?>
IP сервера: 192.168.1.100 Имя сервера: example.com Сетевое имя: web01
Полезно для многосерверной архитектуры - каждый сервер может быть идентифицирован.
Обработка URL с отсутствующим $_SERVER в CLI
<?php
function getCliOrWebUrl(): string
{
if (php_sapi_name() === 'cli') {
// В командной строке адрес не имеет смысла, возвращаем placeholder
return 'cli://localhost/' . basename(__FILE__);
}
// обычный код для веб-сервера
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
return $protocol . '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost') . $_SERVER['REQUEST_URI'];
}
echo getCliOrWebUrl();
?>
В CLI-скриптах (cron, artisan) используется фиктивный адрес, так как HTTP-запроса нет.
Валидация IP-адреса через filter_var
<?php
$ip = '192.168.1.256'; // невалидный
if (filter_var($ip, FILTER_VALIDATE_IP)) {
echo 'IP корректен';
} else {
echo 'IP неверен';
}
?>
IP неверен
Используйте filter_var с флагом FILTER_VALIDATE_IP для проверки адресов перед использованием (например, при сохранении в БД).