b. e. hollenbeck
b. e. hollenbeck

Reputation: 6573

PHP fopen() not creating file if it doesn't already exist

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.

Do I need to suppress the fopen() warning to get it to create the file?

Upvotes: 29

Views: 86364

Answers (6)

Daniel Bingham
Daniel Bingham

Reputation: 12914

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.

However, when you're dealing with file system commands such as fopen, the root directory ('/') is the system root. Not your domain root.

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

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.

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.

Upvotes: 33

Miguel
Miguel

Reputation: 31

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".

Upvotes: 3

Murky Master
Murky Master

Reputation: 101

Don't forget to make sure that SELinux isn't blocking you.

[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

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

Upvotes: 0

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.

I hope this help someone.

Upvotes: 1

Your Common Sense
Your Common Sense

Reputation: 157839

You can always open your file with just "a", it will create a new file as well.
No need to make a condition.

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.

Upvotes: 2

Tobias
Tobias

Reputation: 4397

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.

Upvotes: 20

Related Questions