在PHP脚本中,无论是调用include(), require(), fopen(),还是它们的衍生物,如include_once, require_once,甚至move_uploaded_file(),都经常会遇到错误或警告:
无法打开流:没有这样的文件或目录。
什么是快速找到问题根源的良好流程?
在PHP脚本中,无论是调用include(), require(), fopen(),还是它们的衍生物,如include_once, require_once,甚至move_uploaded_file(),都经常会遇到错误或警告:
无法打开流:没有这样的文件或目录。
什么是快速找到问题根源的良好流程?
当前回答
在PHP中,启动Apache,然后在你的环境中(.env)写下你的数据库名和密码。
其他回答
有很多原因可能会导致这种错误,因此一个好的检查清单可以帮助很大。
让我们考虑一下,我们正在对以下一行进行故障排除:
require "/path/to/file"
检查表
1. 检查文件路径是否有错别字
手动检查(通过视觉检查路径) 或者将require*或include*调用的任何东西移动到它自己的变量中,回显它,复制它,并尝试从终端访问它: $path = "/path/to/file"; echo“Path: $ Path”; 美元需要“路径”; 然后,在终端中: Cat <文件路径粘贴>
2. 根据相对路径和绝对路径的考虑,检查文件路径是否正确
if it is starting by a forward slash "/" then it is not referring to the root of your website's folder (the document root), but to the root of your server. for example, your website's directory might be /users/tony/htdocs if it is not starting by a forward slash then it is either relying on the include path (see below) or the path is relative. If it is relative, then PHP will calculate relatively to the path of the current working directory. thus, not relative to the path of your web site's root, or to the file where you are typing for that reason, always use absolute file paths
最佳实践:
为了让你的脚本健壮,以防你移动东西,同时仍然在运行时生成一个绝对路径,你有两个选择:
use require __DIR__ . "/relative/path/from/current/file". The __DIR__ magic constant returns the directory of the current file. define a SITE_ROOT constant yourself : at the root of your web site's directory, create a file, e.g. config.php in config.php, write define('SITE_ROOT', __DIR__); in every file where you want to reference the site root folder, include config.php, and then use the SITE_ROOT constant wherever you like : require_once __DIR__."/../config.php"; ... require_once SITE_ROOT."/other/file.php";
这两个实践还使应用程序更可移植,因为它不依赖于包括路径之类的ini设置。
3.检查包含路径
另一种既不相对也不绝对地包含文件的方法是依赖include路径。对于库或框架(如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_getpwid:
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
要找出文件的权限,在终端输入以下命令:
ls -l <path/to/file>
看看许可符号表示法
5. 检查PHP设置
如果以上方法都不起作用,那么问题可能是某些PHP设置禁止它访问该文件。
有三个设置可能是相关的:
open_basedir If this is set PHP won't be able to access any file outside of the specified directory (not even through a symbolic link). However, the default behavior is for it not to be set in which case there is no restriction This can be checked by either calling phpinfo() or by using ini_get("open_basedir") You can change the setting either by editing your php.ini file or your httpd.conf file safe mode if this is turned on restrictions might apply. However, this has been removed in PHP 5.4. If you are still on a version that supports safe mode upgrade to a PHP version that is still being supported. allow_url_fopen and allow_url_include this applies only to including or opening files through a network process such as http:// not when trying to include files on the local file system this can be checked with ini_get("allow_url_include") and set with ini_set("allow_url_include", "1")
角情况下
如果以上都不能诊断问题,则可能会发生以下一些特殊情况:
1. 库的包含依赖于include路径
您可能会使用相对路径或绝对路径包含一个库,例如Zend框架。例如:
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
但你还是会得到同样的误差。
之所以会发生这种情况,是因为您已经(成功)包含的文件本身有一个用于另一个文件的include语句,而第二个include语句假定您已经将该库的路径添加到include路径中。
例如,前面提到的Zend框架文件可以包含以下内容:
include "Zend/Mail/Protocol/Exception.php"
既不是相对路径,也不是绝对路径。这里假设Zend框架目录已经添加到include路径。
在这种情况下,唯一可行的解决方案是将目录添加到include路径中。
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()包装文件名。
感谢弗兰·卡诺确定并提出了解决这个问题的方案
Samba股票
如果您有一个Linux测试服务器,并且从Windows客户端工作,那么Samba共享会干扰chmod命令。所以,即使你使用:
chmod -R 777 myfolder
在Linux方面,Unix组\www-data仍然没有写权限是完全可能的。如果您的共享设置为Windows管理员映射到根目录,一个可行的解决方案是:在Windows中,打开权限,禁用带有副本的文件夹的继承,然后授予www-data的完全访问权限。
在PHP中,启动Apache,然后在你的环境中(.env)写下你的数据库名和密码。
下面的PHP设置在PHP .ini中如果设置为不存在的目录也会引发
PHP警告:未知:未能打开流:权限被拒绝 第0行未知
sys_temp_dir
upload_tmp_dir
session.save_path
看看准确的误差
我的代码在所有机器上都工作得很好,但只有在这一台机器上开始出现问题(我猜过去是这样的)。使用echo“document_root”路径进行调试,并仔细查看了错误,发现了这个
警告: 包括(D: / MyProjects / testproject / /功能/ connections.php): 打开流失败:
你很容易就能看出问题在哪里。问题在函数之前
$document_root = $_SERVER['DOCUMENT_ROOT'];
echo "root: $document_root";
include($document_root.'/functions/connections.php');
因此,只需从include中删除提单/,它就可以正常工作。有趣的是这种行为在不同的版本上是不同的。我在笔记本电脑,Macbook Pro和这台PC上运行相同的代码,都工作得很好,直到。希望这能帮助到一些人。
复制过去浏览器中的文件位置,以确保文件存在。有时文件会被意外删除(发生在我身上),这也是我的情况。