Пути к файлам в PHP: правильное указание адресов

Раздел: Файловая система -> Пути файлов

Работа с адресами файлов в PHP

Наиболее эффективное решение для получения корректного адреса файла

Комбинация магической константы __DIR__ и функции realpath() позволяет получить абсолютный путь без символических ссылок и лишних компонентов.


<?php
$baseDir = __DIR__; // путь к каталогу текущего скрипта
$targetPath = realpath($baseDir . '/../includes/config.php');
echo $targetPath;
?>
  

Результат:

/var/www/html/includes/config.php

Такой подход гарантирует, что путь будет нормализован, а слеши приведены к корректному виду для операционной системы.

Возможные проблемы:

  • Если файл не существует, realpath() вернёт false. Нужна проверка.
  • При использовании __DIR__ внутри подключаемого файла путь будет соответствовать местоположению этого файла, а не родительского скрипта.

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

Используется магическая константа __FILE__ или серверная переменная $_SERVER['SCRIPT_FILENAME'].


<?php
echo __FILE__ . PHP_EOL;
echo $_SERVER['SCRIPT_FILENAME'];
?>
  

Результаты могут отличаться при вызове из командной строки или через веб-сервер. __FILE__ всегда возвращает путь к файлу, где она написана.

Типичная ошибка:

Путаница между путями при использовании include и require. Если внутри подключаемого файла написан __FILE__, он покажет путь к подключаемому файлу, а не к главному.

Как получить путь к корню веб-сайта, не зависящий от расположения скрипта?

Наиболее надёжный способ - использовать $_SERVER['DOCUMENT_ROOT'] и добавить свою относительную часть.


<?php
$root = $_SERVER['DOCUMENT_ROOT'];
$path = $root . '/uploads/photo.jpg';
echo $path;
?>
  

Результат:

/var/www/html/uploads/photo.jpg

Ограничения:

DOCUMENT_ROOT отсутствует в CLI-режиме. В некоторых конфигурациях он может не соответствовать реальному корню.

Как преобразовать относительный путь в абсолютный?

Функция realpath() делает это, но требует существования файла. Альтернатива - ручная нормализация с учётом __DIR__ и очисткой компонентов.


<?php
function resolveRelativePath($relative) {
    $parts = explode('/', $relative);
    $result = explode('/', __DIR__);
    foreach ($parts as $part) {
        if ($part === '..') {
            array_pop($result);
        } elseif ($part !== '.') {
            $result[] = $part;
        }
    }
    return implode('/', $result);
}
echo resolveRelativePath('../templates/header.php');
?>
  

Результат (пример):

/var/www/html/templates/header.php

Недостаток:

Такая функция не работает с символическими ссылками и не проверяет существование файла. Желательно использовать realpath() после проверки.

Как правильно работать с путями в разных операционных системах (Windows / Linux)?

Константа DIRECTORY_SEPARATOR и PATH_SEPARATOR помогают создавать кроссплатформенные пути.


<?php
$path = 'config' . DIRECTORY_SEPARATOR . 'app.php';
echo $path;
?>
  

На Windows результат:

config\app.php
, на Linux:
config/app.php

Типичная ошибка:

Жёстко прописанные обратные слеши в коде, которые не работают на Linux. Рекомендуется всегда использовать DIRECTORY_SEPARATOR или нормализовать пути через str_replace.

Как разобрать путь на компоненты: каталог, имя файла, расширение?

Функция pathinfo() возвращает массив с ключами dirname, basename, extension, filename.


<?php
$info = pathinfo('/var/www/html/index.php');
print_r($info);
?>
  

Результат:

Array
(
    [dirname] => /var/www/html
    [basename] => index.php
    [extension] => php
    [filename] => index
)
  

Нюанс:

Если файл не имеет расширения, ключ extension будет пустой строкой. Ключ filename доступен с PHP 5.2.

Как проверить, существует ли файл по заданному адресу?

Функции file_exists(), is_file(), is_dir().


<?php
$file = '/etc/passwd';
if (file_exists($file)) {
    echo 'Файл существует';
}
?>
  

Проблема кэширования:

Результаты этих функций кэшируются для повышения производительности. При частых проверках в течение одного запроса можно получить устаревшие данные. Для сброса кэша используется clearstatcache().

Расширенные примеры работы с адресами файлов

Пример 1: Рекурсивный обход каталога с получением абсолютных путей

Пример

<?php
$directory = __DIR__ . '/project';
$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($iterator as $fileinfo) {
    echo $fileinfo->getRealPath() . PHP_EOL;
}
?>
  

Результат (пример):

/var/www/html/project/index.php
/var/www/html/project/css/style.css
/var/www/html/project/js/script.js
  

Пояснение: использование RecursiveDirectoryIterator с флагом SKIP_DOTS и RecursiveIteratorIterator для обхода всех подкаталогов. Метод getRealPath() возвращает абсолютный путь, разрешая симлинки.

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

Пример

<?php
function buildPath(...$parts) {
    $normalized = [];
    foreach ($parts as $part) {
        $trimmed = trim($part, DIRECTORY_SEPARATOR);
        if ($trimmed !== '') {
            $normalized[] = $trimmed;
        }
    }
    return implode(DIRECTORY_SEPARATOR, $normalized);
}
echo buildPath('/var/www/', 'html', 'uploads', 'image.jpg');
?>
  

Результат:

/var/www/html/uploads/image.jpg

Пояснение: функция собирает части, удаляет лишние разделители и использует константу DIRECTORY_SEPARATOR для кроссплатформенности.

Пример 3: Безопасное сохранение загруженного файла

Пример

<?php
$uploadDir = __DIR__ . DIRECTORY_SEPARATOR . 'uploads';
$originalName = basename($_FILES['userfile']['name']); // защита от path traversal
$targetPath = $uploadDir . DIRECTORY_SEPARATOR . uniqid() . '_' . $originalName;
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $targetPath)) {
    echo 'Файл сохранён: ' . $targetPath;
}
?>
  

Результат:

Файл сохранён: /var/www/html/uploads/5f3a2b1c_image.jpg

Пояснение: basename() удаляет любые попытки выхода за пределы каталога, uniqid() добавляет уникальный префикс, DIRECTORY_SEPARATOR обеспечивает корректный разделитель.

Пример 4: Разрешение символических ссылок и проверка типа файла

Пример

<?php
$link = '/var/www/current'; // символическая ссылка на /var/www/html
$real = realpath($link);
echo $real . PHP_EOL;
echo is_link($link) ? 'Это ссылка' : 'Не ссылка';
?>
  

Результат:

/var/www/html
Это ссылка
  

Пояснение: realpath() возвращает реальный путь, пройдя по цепочке симлинков. is_link() проверяет, является ли переданный путь символической ссылкой.

Пример 5: Извлечение последнего расширения файла

Пример

<?php
$file = '/path/to/file.archive.tar.gz';
$ext = pathinfo($file, PATHINFO_EXTENSION);
echo $ext; // выведет 'gz', а не 'tar.gz'
?>
  

Результат:

gz

Пояснение: pathinfo() с константой PATHINFO_EXTENSION возвращает только часть после последней точки. Для сложных составных расширений требуется дополнительная обработка.

Адрес файла в PHP - comments

En
Php адрес файла (php)