Установка корневого URL в PHP: методы и примеры
Определение базового URL в PHP
Базовый URL (корневой адрес) часто требуется для формирования абсолютных ссылок, редиректов, указания путей к ресурсам. В PHP нет встроенной константы, и разработчики собирают его из переменных сервера. Рассмотрим наиболее эффективное решение, а также альтернативные подходы.
Универсальная функция getBaseUrl()
function getBaseUrl() {
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
$protocol = $_SERVER['HTTP_X_FORWARDED_PROTO'];
}
$host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';
$port = $_SERVER['SERVER_PORT'];
$portSuffix = ($protocol === 'https' && $port == 443) || ($protocol === 'http' && $port == 80) ? '' : ':' . $port;
$base = $protocol . '://' . $host . $portSuffix;
$scriptName = $_SERVER['SCRIPT_NAME'];
$dir = rtrim(dirname($scriptName), '/\\');
$basePath = ($dir !== '.' && $dir !== '') ? $dir : '';
return $base . $basePath;
}
Php создание ссылки (создание ссылки в php)
Код последовательно определяет протокол (с учётом возможного обратного прокси через заголовок X-Forwarded-Proto), хост, порт и путь до корня приложения. Если скрипт выполняется из подпапки вида /myapp/public/index.php, то базовый URL будет содержать /myapp (или /myapp/public в зависимости от точки входа). Рекомендуется использовать эту функцию как основу для проектов.
Типичные проблемы и их решения:
- В CLI окружении переменные $_SERVER отсутствуют. Следует проверять php_sapi_name() и возвращать значение из конфигурации.
- Подмена HTTP_HOST может привести к нежелательным URL. Рекомендуется валидировать хост (например, через белый список доменов).
- Если веб-сервер использует внутренние редиректы или rewriting, значение SCRIPT_NAME может не совпадать с реальным URL-путем. В таких случаях лучше использовать SCRIPT_URI или задавать базовый путь явно.
Как задать базовый URL статически в конфигурации?
Если домен и путь фиксированы, проще определить константу. Это исключает вычисления при каждом запросе.
define('BASE_URL', 'https://example.com/myapp/');
Js php url (javascript и php url)
Цель:
Упрощение кода, повышение производительности. Используется в небольших проектах или приложениях с единственным доменом.
Как быстро получить базовый URL, игнорируя протокол и порт?
Можно взять только HTTP_HOST и добавить 'http://'.
$baseUrl = 'http://' . $_SERVER['HTTP_HOST'];
Php url (url в php)
Цель:
Минимальный код, когда протокол и порт не принципиальны (например, для разработки).
Как задать базовый URL в HTML через тег base?
Внутри шаблона можно указать тег <base href='...'>.
<base href='<?php echo getBaseUrl(); ?>/'>
Url form php (url формы в php)
Цель:
Все относительные ссылки в документе будут разрешаться относительно этого адреса. Удобно для статических ресурсов.
Как использовать переменную SCRIPT_URI для получения базового URL?
Если сервер предоставляет SCRIPT_URI (например, Apache с mod_rewrite), можно разобрать её через parse_url.
if (isset($_SERVER['SCRIPT_URI'])) {
$parts = parse_url($_SERVER['SCRIPT_URI']);
$base = $parts['scheme'] . '://' . $parts['host'];
if (isset($parts['port'])) $base .= ':' . $parts['port'];
$base .= rtrim(dirname($parts['path']), '/');
} else {
// fallback
}
Php url query (url-запрос (query string) в php)
Цель:
Получить точный URL, сформированный сервером.
Как определить базовый URL, используя документ-рут и файловую систему?
Можно вычислить относительный путь от DOCUMENT_ROOT до текущего файла и скомбинировать с доменом.
$docRoot = $_SERVER['DOCUMENT_ROOT'];
$scriptDir = dirname(__FILE__);
$relative = str_replace($docRoot, '', $scriptDir);
$baseUrl = 'http://example.com' . $relative . '/';
Цель:
Полезно, когда требуется узнать путь, не полагаясь на SCRIPT_NAME (например, при симлинках).
Пример 1: Учет обратного прокси с доверенными IP
function getBaseUrlWithProxyCheck() {
$trustedProxies = ['10.0.0.1', '172.16.0.0/12'];
$clientIP = $_SERVER['REMOTE_ADDR'];
$useProxy = false;
if (in_array($clientIP, $trustedProxies)) {
$useProxy = true;
}
if ($useProxy) {
$proto = $_SERVER['HTTP_X_FORWARDED_PROTO'] ?? 'http';
$host = $_SERVER['HTTP_X_FORWARDED_HOST'] ?? $_SERVER['HTTP_HOST'];
$port = $_SERVER['HTTP_X_FORWARDED_PORT'] ?? $_SERVER['SERVER_PORT'];
} else {
$proto = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$port = $_SERVER['SERVER_PORT'] ?? 80;
}
$portSuffix = ($proto === 'https' && $port == 443) || ($proto === 'http' && $port == 80) ? '' : ':' . $port;
$base = $proto . '://' . $host . $portSuffix;
$scriptName = $_SERVER['SCRIPT_NAME'] ?? '';
$basePath = rtrim(dirname($scriptName), '/\\');
if ($basePath === '.' || $basePath === '\\') $basePath = '';
return $base . $basePath;
}
echo getBaseUrlWithProxyCheck();
https://app.example.com/subdir (хост и протокол из заголовков, если IP доверенный)
Пример показывает, как безопасно учитывать заголовки прокси только от доверенных серверов. Без такой проверки клиент может подменить X-Forwarded-Host.
Пример 2: Базовый URL при многосайтовости с подстановкой имени приложения
$currentSite = 'site1';
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$baseUrl = $scheme . '://' . $host . '/' . $currentSite . '/';
if (isset($_SERVER['SERVER_PORT'])) {
$port = (int)$_SERVER['SERVER_PORT'];
if (($scheme === 'https' && $port !== 443) || ($scheme === 'http' && $port !== 80)) {
$baseUrl = $scheme . '://' . $host . ':' . $port . '/' . $currentSite . '/';
}
}
echo $baseUrl;
http://example.com/site1/
Для мультисайтовой архитектуры базовый URL динамически формируется на основе имени сайта, что удобно при развертывании.
Пример 3: Извлечение базового URL с помощью parse_url() из полного URL запроса
$requestUrl = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$parts = parse_url($requestUrl);
$scheme = $parts['scheme'];
$host = $parts['host'];
$port = isset($parts['port']) ? ':' . $parts['port'] : '';
$baseUrl = $scheme . '://' . $host . $port;
echo $baseUrl;
http://example.com:8080
Этот приём использует REQUEST_URI, который включает полный путь и строку запроса. parse_url разбирает его, и берется только схема, хост и порт. Недостаток: не добавляется базовый путь, если приложение лежит в подпапке (потребуется дополнительное извлечение из пути).
Пример 4: Базовый URL для приложения с единой точкой входа (front controller)
$scriptName = $_SERVER['SCRIPT_NAME'];
$basePath = rtrim(dirname($scriptName), '/');
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$baseUrl = $protocol . '://' . $host . $basePath;
$port = $_SERVER['SERVER_PORT'] ?? 80;
if (($protocol === 'https' && $port != 443) || ($protocol === 'http' && $port != 80)) {
$baseUrl .= ':' . $port;
}
echo $baseUrl;
https://example.com/app
Этот пример подходит для фреймворков, где точка входа находится в подпапке, и все URL строятся относительно неё.
Пример 5: Использование конфигурационного файла .env для базового URL
$appUrl = getenv('APP_URL');
if (!$appUrl) {
$appUrl = getBaseUrl();
}
echo $appUrl;
http://localhost:8080/myapp
Хранение базового URL в переменных окружения позволяет легко менять его для разных сред (dev, staging, prod) без изменения кода.