如果文件不存在,PHP fopen() 不创建文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5160362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP fopen() not creating file if it doesn't already exist
提问by b. e. hollenbeck
As part of application logging, I'm attempting to open a local file, and if that file doesn't already exist, to create the new one. Here's what I have:
作为应用程序日志记录的一部分,我试图打开一个本地文件,如果该文件不存在,则创建新文件。这是我所拥有的:
$path = '/home/www/phpapp/logs/myawesome_logfile.txt';
$f = (file_exists($path))? fopen($path, "a+") : fopen($path, "w+");
fwrite($f, $msg);
fclose($f);
chmod($path, 0777);
I've double-checked, and the /logs
directory is chmod 0777, and I even went the extra step of chown'ing it to apache:apache for good measure. Still, when the script goes to open the file, it gives me the warning that the file doesn't exist and bombs out. No file is ever created.
我已经仔细检查过,该/logs
目录是 chmod 0777,我什至采取了额外的步骤,将其 chown'ing 到 apache:apache 以进行良好的衡量。尽管如此,当脚本打开文件时,它会警告我该文件不存在并爆炸。没有文件被创建。
Do I need to suppress the fopen()
warning to get it to create the file?
我是否需要取消fopen()
警告才能创建文件?
回答by Daniel Bingham
When you're working with paths in PHP, the context can matter a great deal. If you're working with urls in a redirection context -- then the root directory ('/') refers to your domain's root. The same goes for paths for linking files or images and for include and require directives.
当您在 PHP 中使用路径时,上下文可能非常重要。如果您在重定向上下文中使用 url,那么根目录 ('/') 是指您的域的根目录。链接文件或图像的路径以及包含和要求指令的路径也是如此。
However, when you're dealing with file system commands such as fopen
, the root directory ('/') is the system root. Not your domain root.
但是,当您处理诸如 之类的文件系统命令时fopen
,根目录 ('/') 是系统根目录。不是您的域根。
To fix this, try giving the full path to the log file you want to open from the system root. For example: /var/www/phpapplication/logs/myLogFile.txt
要解决此问题,请尝试提供要从系统根目录打开的日志文件的完整路径。例如:/var/www/phpapplication/logs/myLogFile.txt
Or you could use $_SERVER['DOCUMENT_ROOT']
as suggested in other answers to access your server's stored value for the path to the document root. The /var/www
part.
或者,您可以$_SERVER['DOCUMENT_ROOT']
按照其他答案中的建议使用来访问服务器存储的文档根路径的值。的/var/www
一部分。
You can also use the __DIR__
magic constant in some cases. Note that __DIR__
will be the directory the current file is in, which is not necessarily the same as your application's root. So for example, if your application's root is /var/www/application
and you're working in /var/www/application/src/controllers/my_controller.php
, then __DIR__
will be /var/www/application/src/controllers
. See here in the PHP documentation.
__DIR__
在某些情况下,您还可以使用魔术常量。请注意,这__DIR__
将是当前文件所在的目录,它不一定与您的应用程序的根目录相同。因此,例如,如果您的应用程序的根是/var/www/application
并且您正在使用/var/www/application/src/controllers/my_controller.php
,那么__DIR__
将是/var/www/application/src/controllers
。请参阅 PHP 文档中的此处。
回答by Tobias
Have you tried this?
你试过这个吗?
$msg = "I'm a line that is a message.\n";
$path = $_SERVER['DOCUMENT_ROOT'] . '/logs/myawesome_logfile.txt';
$f = fopen($path, "a+");
fwrite($f, $msg);
fclose($f);
chmod($path, 0777);
The server you're working on could have jailed you to only work in the phpapp's directory and its subdirectories.
您正在使用的服务器可能会让您只能在 phpapp 的目录及其子目录中工作。
回答by Miguel
One way I got around this problem in UBUNTU 14.04 was by right clicking on the directory where the file is located and changing the permissions of "others" to "create and delete files".
我在 UBUNTU 14.04 中解决这个问题的一种方法是右键单击文件所在的目录并将“其他人”的权限更改为“创建和删除文件”。
回答by Your Common Sense
You can always open your file with just "a"
, it will create a new file as well.
No need to make a condition.
您可以随时使用 just 打开文件"a"
,它也会创建一个新文件。
没必要做条件。
However, the main issue with your code is understanding the difference between physical filesystem and virtual web-server, which have been perfectly explained already.
但是,您的代码的主要问题是理解物理文件系统和虚拟网络服务器之间的区别,这已经得到了完美的解释。
Note that you should provide your question with exact copy of error message. It contains a ton of extremely useful information, it's not like an oath "I won't create your file, go away!" but it's through explanation of what and why is going wrong. If you don't care of such useful info yourself, you have to provide it to ones whom asking for help.
请注意,您应该向问题提供错误消息的准确副本。它包含了大量非常有用的信息,这不像是一句“我不会创建你的文件,滚开!”的誓言。但它是通过解释什么和为什么出了问题。如果您自己不关心这些有用的信息,则必须将其提供给寻求帮助的人。
回答by Jose Manuel Blasco Galdón
The path of the file must be with the server root. I could achieve this using the phpinfo() method inside the document I wanted to know. So when you use phpinfo() you will see a information document. If you find for _SERVER["SCRIPT_FILENAME"] you will see the absolute path of your file.
文件的路径必须是服务器根目录。我可以使用我想知道的文档中的 phpinfo() 方法来实现这一点。因此,当您使用 phpinfo() 时,您将看到一个信息文档。如果您找到 _SERVER["SCRIPT_FILENAME"] ,您将看到文件的绝对路径。
I hope this help someone.
我希望这对某人有帮助。
回答by Murky Master
Don't forget to make sure that SELinux isn't blocking you.
不要忘记确保 SELinux 没有阻止您。
[root@yourbox]# audit2allow < /var/log/audit/audit.log
#============= httpd_t ==============
#!!!! This avc can be allowed using the boolean 'httpd_unified' allow httpd_t httpd_sys_content_t:dir { write add_name };
#!!!! This avc can be allowed using the boolean 'httpd_unified' allow httpd_t httpd_sys_content_t:file { write create }; [root@yourbox]# audit2allow -a -M my_httpd
[root@yourbox]# audit2allow < /var/log/audit/audit.log
#============== httpd_t ==============
#!! !! 可以使用布尔值 'httpd_unified' 允许该 avc 允许 httpd_t httpd_sys_content_t:dir { write add_name };
#!!!!!! 可以使用布尔值 'httpd_unified' 允许此 avc 允许 httpd_t httpd_sys_content_t:file { write create }; [root@yourbox]# audit2allow -a -M my_httpd
Note:
笔记:
To make this policy package active, execute:
要激活此策略包,请执行:
semodule -i my_httpd.pp
[root@yourbox]# semodule -i my_httpd.pp
[root@yourbox]# systemctl restart httpd
semodule -i my_httpd.pp
[root@yourbox]# semodule -i my_httpd.pp
[root@ yourbox ]# systemctl restart httpd