#Что происходит и как определить неисправность
Относительный путь PHP может разрешаться не из каталога самого скрипта, а относительно текущего рабочего каталога процесса. Поэтому include("config.php") или file_get_contents("data/file.txt") иногда работает из CLI и ломается в веб-запросе либо после вызова chdir().
#Вероятные причины и признаки
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Непредсказуемый рабочий каталогНепредсказуемый рабочий каталог. getcwd() различается при запуске через cron и PHP-FPM | getcwd() различается при запуске через cron и PHP-FPM | Привязать путь к __DIR__ файла, которому нужен ресурс. |
| Ресурс не существует по рассчитанному адресуРесурс не существует по рассчитанному адресу. Результат realpath() равен false, имя файла и регистр расходятся | Результат realpath() равен false, имя файла и регистр расходятся | Проверить фактический абсолютный путь. |
| Процесс не может читать файлПроцесс не может читать файл. Файл есть, но в журнале Permission denied или open_basedir restriction | Файл есть, но в журнале Permission denied или open_basedir restriction | Проверить ограничения доступа, не открывая весь каталог миру. |
#Пошаговая диагностика и исправление
- Выпишите точное имя отсутствующего файлаВ журнале PHP найдите failed to open stream, No such file or directory или open_basedir restriction. Запишите имя файла, вызвавшую строку и способ запуска (веб, cron, CLI). Под одинаковым текстом ошибки бывают разные причины.
- Проверьте расположение файлаВ панели управления файлами откройте корень сайта и нужную подпапку. Убедитесь в точном написании, регистре букв и расширении. Linux различает Config.php и config.php. Не переносите файл в общедоступный каталог ради устранения ошибки.
- Сравните каталог процесса с каталогом кодаНа тестовой копии добавьте в журнал getcwd() и __DIR__ в месте ошибки, без вывода служебных путей пользователю. Если они различны, относительный путь может оказаться привязан к другому месту.
- Соберите путь относительно текущего PHP-файлаВ редакторе кода на тестовой копии замените опасный относительный путь на __DIR__ . "/config.php". Если файл лежит выше, используйте dirname(__DIR__) и заранее проверьте конечный путь. Код ниже — иллюстрация для файла, расположенного рядом.
- Пример кода по темеPHPПример фрагмента PHP для тестовой копии; не выполнять в оболочке и не размещать конфигурацию публично.
<?php $path = __DIR__ . "/config.php"; if (!is_file($path) || !is_readable($path)) { throw new RuntimeException("Configuration file is unavailable"); } require $path;
- Проверьте контекст планировщикаЕсли ошибка появляется лишь по расписанию, в SSH посмотрите рабочий каталог задания и путь к интерпретатору в crontab/панели. Пропишите полный путь до PHP-скрипта, а все внутренние зависимости оставьте привязанными к __DIR__; не рассчитывайте на cd, случайно заданный пользователем.
- Исследуйте права и open_basedirЕсли файл существует, проверьте владельца/группу и право на проход по родительским каталогам для пользователя PHP-FPM. Ограничение open_basedir расширяйте только до необходимой директории и только с разрешения администратора. Не делайте chmod -R 777.
- Учтите относительные пути в подключаемых файлахПри require нескольких файлов __DIR__ в каждом из них указывает на каталог соответствующего файла; это полезно, но не заменяет проверки расположения ресурса. Для файлов загрузки и пользовательских имён проверьте нормализацию пути, чтобы избежать выхода за каталог.
- Проверьте два способа исполненияОткройте маршрут через HTTPS и повторите тот же сценарий из фонового обработчика на тестовом экземпляре. В обоих случаях файл должен быть доступен без изменения глобального рабочего каталога. При сбое восстановите прежний код и зафиксируйте вычисленный путь.
#Как проверить результат
На тестовом запросе и в планировщике отсутствует ошибка открытия файла, ресурс находится только в ожидаемом безопасном каталоге, а журнал не раскрывает служебные пути в HTML.
#Если не помогло
Если __DIR__ указывает верно, но ошибка остаётся, различайте отсутствие файла, права доступа и open_basedir: они требуют разных исправлений. Смена cwd на весь проект часто маскирует дефект.