PHP fopen() не создает файл, если он еще не существует

в рамках ведения журнала приложение, которое я пытаюсь открыть локальный файл, и если файл еще не существует, создать новый. Вот что у меня есть:

$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);

Я дважды проверил, и /logs каталог chmod 0777, и я даже пошел дополнительный шаг chown'ING его apache:apache для хорошей меры. Тем не менее, когда скрипт открывает файл, он дает мне предупреждение о том, что файл не существует, и бомбит. Файл никогда не создается.

Я нужно подавить fopen() предупреждение, чтобы заставить его создать файл?

6 ответов


когда вы работаете с путями в PHP, контекст имеет большое значение. Если вы работаете с URL-адресами в контексте перенаправления , корневой каталог ( ' / ' ) ссылается на корневой каталог вашего домена. То же самое касается путей для связывания файлов или изображений и директив include и require.

однако, когда вы имеете дело с командами файловой системы, такими как fopen корневой каталог ('/') является корневая система. Не ваш домен root.

чтобы исправить это, попробуйте предоставление полного пути к файлу журнала, который вы хотите открыть из системного корня. Например: /var/www/phpapplication/logs/myLogFile.txt

или вы можете использовать $_SERVER['DOCUMENT_ROOT'] как предложено в других ответах для доступа к сохраненному значению вашего сервера для пути к корню документа. The /var/www часть.

вы также можете использовать __DIR__ магическая константа в некоторых случаях. Обратите внимание, что __DIR__ будет каталогом, в котором находится текущий файл, который не обязательно совпадает с корнем вашего приложения. Так, например, если корень вашего приложения /var/www/application и вы работаете в /var/www/application/src/controllers/my_controller.php, потом __DIR__ будет /var/www/application/src/controllers. см. здесь, в документации по PHP.


вы пробовали это?

$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);

сервер, на котором вы работаете, мог бы посадить вас в тюрьму только для работы в каталоге phpapp и его подкаталогах.


один из способов обойти эту проблему в UBUNTU 14.04 - щелкнуть правой кнопкой мыши по каталогу, где находится файл, и изменить разрешения "другие" на "создание и удаление файлов".


вы всегда можете открыть файл с помощью just "a", Он также создаст новый файл.
Не нужно ставить условие.

однако основной проблемой вашего кода является понимание разницы между физической файловой системой и виртуальным веб-сервером, что уже было прекрасно объяснено.

обратите внимание, что вы должны предоставить свой вопрос с точной копией сообщения об ошибке. Он содержит тонну чрезвычайно полезной информации, это не похоже на клятву "я не буду создайте свой файл, уходите!"но это через объяснение того, что и почему происходит не так. Если вы сами не заботитесь о такой полезной информации, вы должны предоставить ее тем, кто просит о помощи.


путь к файлу должен быть с корневым сервером. Я мог бы достичь этого, используя функцию phpinfo() метод внутри документа, который я хотел знать. Поэтому при использовании phpinfo () вы увидите информационный документ. Если вы найдете для _SERVER ["SCRIPT_FILENAME"] вы увидите абсолютный путь к вашему файлу.

Я надеюсь, что это поможет кому-то.


Не забудьте убедиться, что SELinux не блокирует вас.

[root@yourbox]# audit2allow #============= httpd_t ==============
#!!!! Этот avc можно разрешить с помощью логического "httpd_unified" разрешить httpd_t httpd_sys_content_t: dir { написать add_name };
#!!!! Этот avc можно разрешить с помощью логического "httpd_unified" разрешить httpd_t httpd_sys_content_t: файл { написать создать }; [root@yourbox]# audit2allow - a-M my_httpd

Примечание:

чтобы сделать этот пакет активной политики, выполните:

semodule-i my_httpd.pp

[root@yourbox]# semodule-i my_httpd.стр
[root@yourbox]# systemctl перезапустить httpd