有很多原因导致人们可能遇到这个错误,因此一个好的检查列表首先要检查的内容有很大帮助。
让我们考虑一下我们正在对以下行进行故障排除:require "/path/to/file"
清单
1.检查拼写错误的文件路径手动检查(通过目视检查路径)
或移动任何被其调用require*或调用include*其自己的变量,回显它,复制它,并尝试从终端访问它:$path = "/path/to/file";echo "Path : $path";require "$path";
然后,在一个终端:cat
2.检查相对于绝对路径注意事项的文件路径是否正确如果它以正斜杠“/”开头,那么它不是指网站文件夹的根目录(文档根目录),而是指服务器的根目录。例如,您的网站目录可能是 /users/tony/htdocs
如果它不是以正斜杠开始,那么它要么依赖于包含路径(见下文),要么路径是相对的。如果是相对的,则PHP将相对于当前工作目录的路径进行计算。因此,不是相对于网站根目录的路径,也不是相对于您键入的文件
因此,始终使用绝对文件路径
最佳做法:
为了使您的脚本在您移动的同时保持健壮,同时仍然在运行时生成绝对路径,您有两个选择:用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";
这两种做法也使您的应用程序更具可移植性,因为它不依赖于包含路径等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
5.检查PHP设置
如果以上都不起作用,那么问题可能是某些PHP设置禁止它访问该文件。
三个设置可能是相关的:如果设置了此项,PHP将无法访问指定目录之外的任何文件(甚至不能通过符号链接)。
但是,默认行为是不设置它,在这种情况下没有限制
这可以通过调用phpinfo()或使用来检查ini_get("open_basedir")
您可以通过编辑php.ini文件或httpd.conf文件来更改设置如果启用此限制可能适用。但是,这已在PHP 5.4中删除。如果您仍然使用支持安全模式升级到仍受支持的PHP版本的版本。这仅适用于在尝试在本地文件系统上包含文件时通过网络进程(例如http://)包含或打开文件
这可以通过检查ini_get("allow_url_include")和设置ini_set("allow_url_include", "1")
转角案件
如果上述任何一个都无法诊断问题,则可能会发生以下特殊情况:
1.包含依赖于包含路径的库
您可以使用相对路径或绝对路径包含库,例如Zend框架。例如 :require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
但是你仍然会遇到同样的错误。
这可能是因为您(成功)包含的文件本身具有另一个文件的include语句,而第二个include语句假定您已将该库的路径添加到包含路径。
例如,之前提到的Zend框架文件可能包含以下内容:include "Zend/Mail/Protocol/Exception.php"
这既不是相对路径的包含,也不是绝对路径。假设Zend框架目录已添加到包含路径。
在这种情况下,唯一可行的解决方案是将目录添加到包含路径。
2. SELinux
如果您正在运行安全增强型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拒绝访问文件的原因可能有多种,具体取决于您的策略。所以你需要调查一下。这是一个专门为Web服务器配置SELinux的教程。
3. Symfony
如果您正在使用Symfony,并在上传到服务器时遇到此错误,则可能是应用程序的缓存未被重置,因为app/cache已上载或尚未清除缓存。
您可以通过运行以下控制台命令来测试并修复此问题:cache:clear
4. Zip文件中的非ACSII字符
显然,zip->close()当zip中的某些文件的文件名中包含非ASCII字符(例如“é”)时,也会发生此错误。
可能的解决方案是utf8_decode()在创建目标文件之前包装文件名。
致Fran Cano确认并建议解决此问题的方法