Есть много причин, по которым можно столкнуться с этой ошибкой, и, таким образом, хороший контрольный список того, что проверять в первую очередь, значительно помогает.
Давайте рассмотрим, что мы устраняем неисправности в следующей строке:
require "/path/to/file"
контрольный список
1. Проверьте путь к файлу для опечаток
- либо проверить вручную (визуально проверяя путь)
или переместите все, что вызвано require*
или include*
к своей собственной переменной, отобразите его, скопируйте и попробуйте получить доступ к нему из терминала:
$path = "/path/to/file";
echo "Path : $path";
require "$path";
Затем в терминале:
cat <file path pasted>
2. Проверьте правильность пути к файлу относительно относительного или абсолютного пути
- если он начинается с косой черты "/", то это относится не к корню папки вашего сайта (корню документа), а к корню вашего сервера.
- например, каталог вашего сайта может быть
/users/tony/htdocs
- если он не начинается с косой черты, то он либо полагается на путь включения (см. ниже), либо путь является относительным. Если это относительно, то PHP будет рассчитывать относительно пути текущего рабочего каталога .
- таким образом, не относительно пути корня вашего веб-сайта или файла, в котором вы печатаете
- по этой причине всегда используйте абсолютные пути к файлам
Лучшие практики :
Чтобы сделать ваш скрипт надежным в случае, если вы перемещаете вещи, все еще генерируя абсолютный путь во время выполнения, у вас есть 2 варианта:
- использовать
require __DIR__ . "/relative/path/from/current/file"
. __DIR__
Постоянная магия возвращает каталог текущего файла.
Определите SITE_ROOT
константу самостоятельно:
- в корне каталога вашего веб-сайта создайте файл, например
config.php
в config.php
, пишут
define('SITE_ROOT', __DIR__);
в каждом файле, где вы хотите сослаться на корневую папку сайта, включите config.php
, а затем используйте SITE_ROOT
константу, где хотите:
require_once __DIR__."/../config.php";
...
require_once SITE_ROOT."/other/file.php";
Эти 2 метода также делают ваше приложение более переносимым, поскольку оно не зависит от настроек ini, таких как путь включения.
3. Проверьте ваш путь включения
Другой способ включения файлов, ни относительный, ни сугубо абсолютный, заключается в использовании пути включения . Это часто относится к библиотекам или платформам, таким как Zend.
Такое включение будет выглядеть так:
include "Zend/Mail/Protocol/Imap.php"
В этом случае вам нужно убедиться, что папка, в которой находится «Zend», является частью пути включения.
Вы можете проверить путь включения с помощью:
echo get_include_path();
Вы можете добавить в него папку с помощью:
set_include_path(get_include_path().":"."/path/to/new/folder");
4. Убедитесь, что ваш сервер имеет доступ к этому файлу
Может случиться так, что все вместе, пользователь, выполняющий процесс сервера (Apache или PHP), просто не имеет разрешения на чтение или запись в этот файл.
Чтобы проверить, под каким пользователем работает сервер, вы можете использовать posix_getpwuid :
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
Чтобы узнать разрешения для файла, введите в терминале следующую команду:
ls -l <path/to/file>
и посмотрите на символьную запись разрешения
5. Проверьте настройки PHP
Если ничего из вышеперечисленного не сработало, возможно, проблема в том, что некоторые настройки PHP запрещают ему доступ к этому файлу.
Три настройки могут быть актуальны:
- open_basedir
- Если это установлено, PHP не сможет получить доступ ни к какому файлу за пределами указанного каталога (даже через символическую ссылку).
- Тем не менее, поведение по умолчанию для него не должно быть установлено, в этом случае нет никаких ограничений
- Это можно проверить по телефону
phpinfo()
или с помощьюini_get("open_basedir")
- Вы можете изменить настройку, отредактировав файл php.ini или файл httpd.conf.
- безопасный режим
- если это включено, ограничения могут применяться. Однако это было удалено в PHP 5.4. Если вы все еще используете версию, которая поддерживает безопасный режим, обновите ее до версии PHP, которая все еще поддерживается .
- allow_url_fopen и allow_url_include
- это относится только к включению или открытию файлов через сетевой процесс, такой как http: // не при попытке включить файлы в локальную файловую систему
- это можно проверить с помощью
ini_get("allow_url_include")
и установить сini_set("allow_url_include", "1")
Угловые чехлы
Если ничего из перечисленного не позволяет диагностировать проблему, вот несколько особых ситуаций, которые могут произойти:
1. Включение библиотеки с использованием пути включения
Может случиться так, что вы включите библиотеку, например, Zend Framework, используя относительный или абсолютный путь. Например :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
Но тогда вы все равно получаете такую же ошибку.
Это может произойти, потому что файл, который вы (успешно) включили, сам имеет оператор включения для другого файла, и этот второй оператор включения предполагает, что вы добавили путь этой библиотеки к пути включения.
Например, упомянутый ранее файл Zend Framework может содержать следующее:
include "Zend/Mail/Protocol/Exception.php"
который не является ни включением ни по относительному пути, ни по абсолютному пути. Предполагается, что каталог Zend Framework был добавлен в путь включения.
В таком случае единственное практическое решение - добавить каталог к вашему пути включения.
2. SELinux
Если вы работаете в Security-Enhanced Linux, это может быть причиной проблемы, так как вы отказываете в доступе к файлу с сервера.
Чтобы проверить, включен ли SELinux в вашей системе, выполните sestatus
команду в терминале. Если команда не существует, значит SELinux отсутствует в вашей системе. Если он существует, то он должен сказать вам, применяется ли он или нет.
Чтобы проверить, являются ли политики SELinux причиной проблемы, вы можете временно отключить ее. Однако будьте осторожны, так как это полностью отключит защиту. Не делайте этого на вашем производственном сервере.
setenforce 0
Если у вас больше нет проблемы с выключенным SELinux, то это является основной причиной.
Чтобы решить эту проблему , вам необходимо соответствующим образом настроить SELinux.
Следующие типы контекста будут необходимы:
httpd_sys_content_t
для файлов, которые вы хотите, чтобы ваш сервер мог читать
httpd_sys_rw_content_t
для файлов, к которым вы хотите доступ для чтения и записи
httpd_log_t
для файлов журнала
httpd_cache_t
для каталога кеша
Например, чтобы назначить httpd_sys_content_t
тип контекста корневому каталогу вашего сайта, запустите:
semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
Если ваш файл находится в домашнем каталоге, вам также нужно включить httpd_enable_homedirs
логическое значение:
setsebool -P httpd_enable_homedirs 1
В любом случае может быть множество причин, по которым SELinux может запретить доступ к файлу, в зависимости от ваших политик. Так что вам нужно будет выяснить это. Вот учебник, посвященный настройке SELinux для веб-сервера.
3. Symfony
Если вы используете Symfony и сталкиваетесь с этой ошибкой при загрузке на сервер, возможно, кэш приложения не был сброшен, либо потому, app/cache
что был загружен, либо этот кэш не был очищен.
Вы можете проверить и исправить это, выполнив следующую консольную команду:
cache:clear
4. Не ACSII символы внутри Zip-файла
По-видимому, эта ошибка также может возникать при вызове, zip->close()
когда в некоторых файлах внутри zip-файла есть не-ASCII-символы в имени файла, такие как «é».
Потенциальным решением является завершение имени файла utf8_decode()
перед созданием целевого файла.
Кредиты Фран Кано для выявления и предложения решения этой проблемы