Способы извлечения путей в PHP: от файла до корня сайта

Раздел: Программирование на PHP -> Управление путями

В веб-разработке часто требуется получить путь к текущему PHP-скрипту, его директории, корню сайта или URL страницы. Это необходимо для подключения файлов, создания ссылок, работы с файловой системой. В PHP существует несколько способов, каждый из которых подходит для конкретной задачи.

Основные подходы к получению путей

Как получить полный путь к текущему PHP-файлу?

Основное и наиболее надёжное решение - использование магической константы __FILE__. Она возвращает абсолютный путь к файлу, в котором была вызвана. Константа работает во всех версиях PHP и не зависит от внешних факторов, таких как web-сервер или текущая рабочая директория.

<?php echo __FILE__; ?>

Php get path (получение текущего пути в php)

Пример вывода на сервере Linux: /var/www/html/site/index.php

Проблема: при использовании внутри файла, который был включён через include или require, __FILE__ указывает на сам включённый файл, а не на вызывающий скрипт. Для получения пути к главному скрипту запроса используется $_SERVER['SCRIPT_FILENAME']. Также __FILE__ может содержать символические ссылки; для их разрешения применяется realpath().

Как узнать директорию, где находится скрипт?

Для получения директории текущего файла можно использовать функцию dirname() в сочетании с __FILE__ или константу __DIR__ (доступна с PHP 5.3).

<?php
$dir1 = dirname(__FILE__);
$dir2 = __DIR__;
echo $dir1 . "\n" . $dir2;
?>

Результат: /var/www/html/site (без завершающего слеша). Для канонизации пути рекомендовано использовать realpath(__DIR__).

Типичная ошибка: забывают, что __DIR__ не содержит завершающего слеша. Это может привести к проблемам при конкатенации с последующими папками. Решение - добавлять DIRECTORY_SEPARATOR или использовать rtrim().

Как получить корень документа (Document Root)?

Для определения пути к корневой директории сайта (откуда сервер обрабатывает запросы) используется элемент суперглобального массива $_SERVER['DOCUMENT_ROOT'].

<?php
echo $_SERVER['DOCUMENT_ROOT'];
?>

Результат: /var/www/html (зависит от конфигурации).

Проблемы: настройка DOCUMENT_ROOT может быть отключена (если в php.ini register_globals выключено, но это не должно влиять). Может возвращать значение с завершающим слешем или без. При использовании виртуальных хостов или Chroot может быть неверное значение. Рекомендуется проверять и нормализовать с realpath().

Как получить URL текущей страницы?

Для полного URL (протокол + хост + URI) используется комбинация нескольких элементов $_SERVER.

<?php
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$uri = $_SERVER['REQUEST_URI'];
$url = $protocol . '://' . $host . $uri;
echo $url;
?>

Результат: http://example.com/index.php?id=5.

Проблемы: при использовании нестандартного порта, отличного от 80 или 443, его необходимо явно добавлять. $_SERVER['HTTP_HOST'] может быть не задан в некоторых окружениях (CLI). Альтернатива - $_SERVER['SERVER_NAME'].

Как получить физический путь на основе URL?

Для преобразования запрошенного URL в файловый путь можно объединить $_SERVER['DOCUMENT_ROOT'] и $_SERVER['REQUEST_URI'], после чего обработать realpath().

<?php
$phys = realpath($_SERVER['DOCUMENT_ROOT'] . $_SERVER['REQUEST_URI']);
if ($phys) {
    echo $phys;
} else {
    echo 'Путь не существует';
}
?>

Пример вывода: /var/www/html/article.php.

Ошибка: $_SERVER['REQUEST_URI'] может содержать query string, что надо отсекать (strtok()). При использовании mod_rewrite физического пути может не существовать. Также опасно для безопасности - возможен path traversal, если URI обрабатывается без проверки.

Как получить текущую рабочую директорию (CWD)?

Функция getcwd() возвращает текущую рабочую директорию процесса PHP.

<?php
echo getcwd();
?>

Результат: может быть /var/www/html или /tmp в зависимости от контекста.

Проблема: CWD изменяется после вызова chdir(). В CLI она часто совпадает с местом запуска скрипта, но не с путём самого скрипта. Для задач, где нужна директория скрипта, __DIR__ надёжнее.

Как получить путь к файлу, который вызвал include?

Если внутри инклуда требуется узнать путь к основному скрипту (который сделал запрос), используется $_SERVER['SCRIPT_FILENAME'] (имя исполняемого скрипта). Альтернативный способ - debug_backtrace().

<?php
// in included file
echo $_SERVER['SCRIPT_FILENAME'];
?>

Пример вывода: /var/www/html/index.php.

При использовании debug_backtrace() следует учитывать производительность и то, что глубина стека может быть ограничена. $_SERVER['SCRIPT_FILENAME'] не всегда доступен в CLI-сценариях (там может быть отсутствовать или содержать путь к php-бинарнику).

Расширенные примеры и редкие случаи

Разрешение символических ссылок с помощью realpath

Функция realpath() преобразует путь с симлинками и относительными сегментами в абсолютный канонический путь.

Пример
<?php
$path = __DIR__ . '/../config/db.php';
$canonical = realpath($path);
if ($canonical) {
    echo $canonical;
} else {
    echo 'Ошибка: путь не существует';
}
?>
/var/www/site/config/db.php

В случае, если симлинк ведёт на другую файловую систему, realpath() всё равно вернёт реальный путь.

Получение относительного пути от корня документа

Часто требуется преобразовать абсолютный путь скрипта в относительный URL. Это можно сделать, если известен $_SERVER['DOCUMENT_ROOT'].

Пример
<?php
$abs = __DIR__ . '/assets/image.jpg';
$docRoot = $_SERVER['DOCUMENT_ROOT'];
// Убираем корень документа из начала пути
if (strpos($abs, $docRoot) === 0) {
    $relative = substr($abs, strlen($docRoot));
    echo $relative;
} else {
    echo 'Путь вне корня документа';
}
?>
/assets/image.jpg

Обратите внимание: после удаления корня может остаться начальный слеш, что нормально для URL.

Сравнение путей с учётом чувствительности регистра

На Linux файловая система чувствительна к регистру, на Windows - нет. Для надёжного сравнения путей рекомендуется привести их к единому регистру с помощью strtolower() после realpath().

Пример
<?php
$path1 = realpath('/var/www/html/File.php');
$path2 = realpath('/var/www/html/file.php');
if (strtolower($path1) === strtolower($path2)) {
    echo 'Пути указывают на один файл (с точностью до регистра)';
}
?>

Вывод: строки могут совпадать или не совпадать в зависимости от реального существования файлов. Такой подход полезен для кэширования.

Получение списка всех включённых файлов с их путями

Для отладки или аудита может потребоваться массив всех файлов, подключенных через include/require. Для этого используется get_included_files().

Пример
<?php
// подключим несколько файлов
include 'config.php';
include 'functions.php';
$included = get_included_files();
print_r($included);
?>
Array
(
    [0] => /var/www/html/index.php
    [1] => /var/www/html/config.php
    [2] => /var/www/html/functions.php
)

Функция возвращает абсолютные пути, уже нормализованные. Это работает и с require_once, и с include_once.

Кросс-платформенная обработка путей: DIRECTORY_SEPARATOR

Windows использует обратную косую черту (\), Linux - прямую (/). Для совместимости используйте константу DIRECTORY_SEPARATOR или просто /, так как PHP под Windows тоже понимает прямую черту.

Пример
<?php
$path = __DIR__ . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'file.txt';
echo $path;
// То же самое с /:
echo __DIR__ . '/data/file.txt';
?>
/var/www/html/data/file.txt

При работе с пользовательскими путями рекомендуется заменять обратные косые черты на прямые с помощью str_replace('\\', '/', $path).

Создание универсальной функции для получения пути скрипта

Иногда необходимо получить путь к папке, где лежит главный скрипт, даже если текущий файл является инклудом. Функция может использовать $_SERVER['SCRIPT_FILENAME'].

Пример
<?php
function getScriptDir() {
    $script = $_SERVER['SCRIPT_FILENAME'];
    if (!$script) {
        // fallback для CLI
        $script = $_SERVER['PHP_SELF'] ?? __FILE__;
    }
    return dirname(realpath($script));
}
echo getScriptDir();
?>
/var/www/html

Эта функция надёжна для веб-среды, но в CLI может дать неверный результат, поэтому требуется проверка.

Получение текущего пути в PHP - comments

En
Php get path (php)