Введение в создание и управление файлами в PHP
Узнайте, как создавать и записывать файлы в PHP с помощью fopen(), fwrite(), fclose() и file_put_contents(). Режимы файлов, добавление данных и обработка ошибок.
PHP работает на сервере, поэтому может читать и записывать реальные файлы на диске — генерируемые отчёты, кэшированный HTML, записи журналов, экспортированные CSV, загруженный пользовательский контент и конфигурационные файлы. В этой главе рассматривается основной процесс создания и записи файлов: открытие дескриптора файла с нужным режимом, запись данных и закрытие дескриптора. Также объясняется, когда лучше использовать более простые однострочные вспомогательные функции.
В PHP существует два семейства инструментов для записи файлов:
- Потоковые дескрипторы —
fopen()/fwrite()/fclose(). Лучший выбор, когда запись ведётся поэтапно (добавление строк в журнал, потоковый вывод больших данных) и требуется точный контроль над режимом файла. - Однократные вспомогательные функции —
file_put_contents(). Лучший выбор, когда вся строка уже находится в памяти и нужно просто записать её в файл одним вызовом.
Сначала рассмотрим потоковый подход, поскольку понимание режимов — ключ ко всему остальному.
Создание и запись файла с помощью fopen()
Чтобы записать в файл, сначала откройте его с помощью fopen(). Функция принимает путь к файлу и строку режима и возвращает дескриптор файла (ресурс), с которым работают остальные функции:
<?php
$file = fopen("example.txt", "w"); // open for writing, truncating the file
fwrite($file, "This is an example.\n");
fclose($file); // always close the handleЧто делает каждая строка:
fopen("example.txt", "w")открываетexample.txtв режиме записи. Если файл не существует, он создаётся; если существует — его содержимое стирается (усекается до нулевой длины).fwrite()записывает строку в файл и возвращает количество записанных байт (илиfalseв случае ошибки).fclose()сбрасывает буферизованные данные и освобождает дескриптор. Пропуск этого вызова может привести к тому, что данные останутся незаписанными до завершения скрипта.
Относительный путь вида
"example.txt"разрешается относительно текущего рабочего каталога скрипта. Для безопасности и предсказуемости рекомендуется использовать абсолютный путь, например__DIR__ . "/example.txt".
Режимы файлов
Режим, передаваемый в fopen(), определяет, будет ли файл создан, усечён или дополнен, а также доступен ли он для чтения. Вот режимы, важные для создания и записи:
| Режим | Описание | Создаёт файл? | Существующее содержимое | Указатель начинается с |
|---|---|---|---|---|
"w" | Только запись | Да | Стирается | Начала |
"w+" | Чтение + запись | Да | Стирается | Начала |
"a" | Только добавление | Да | Сохраняется | Конца |
"a+" | Чтение + добавление | Да | Сохраняется | Конца |
"x" | Только запись, ошибка если файл существует | Да (только если новый) | — | Начала |
"x+" | Чтение + запись, ошибка если файл существует | Да (только если новый) | — | Начала |
Используйте "x", когда нельзя перезаписать существующий файл — например, при записи файла блокировки. Используйте "a" для журналов, где каждый запуск должен добавлять данные в файл, а не стирать его.
Добавление данных вместо перезаписи
Очень распространённая ошибка — использование "w" для журнала и недоумение, почему файл всегда содержит лишь одну строку. Открывайте файл с режимом "a", чтобы сохранять предыдущее содержимое и добавлять данные в конец:
<?php
$log = fopen("app.log", "a"); // append mode — never erases
fwrite($log, "[" . date("Y-m-d H:i:s") . "] User logged in\n");
fclose($log);Запустите это дважды — и файл будет содержать две строки с временными метками вместо одной.
Быстрый способ: file_put_contents()
Когда всё содержимое уже есть в виде строки, file_put_contents() выполняет открытие, запись и закрытие в одном вызове:
<?php
// Overwrite (or create) the file with this exact content:
file_put_contents("greeting.txt", "Hello, world!\n");
// Append instead of overwriting:
file_put_contents("app.log", "another line\n", FILE_APPEND);Функция возвращает количество записанных байт или false в случае ошибки. Это наиболее удобный выбор для небольших данных, хранящихся в памяти. Используйте fopen()/fwrite(), когда запись ведётся в цикле или дескриптор нужно держать открытым для нескольких операций.
Чтение записанных данных
Чтобы проверить результат записи, откройте файл в режиме чтения ("r") и прочитайте его. Сопутствующая глава Открытие/чтение файлов в PHP рассматривает это подробно, но потоковый вариант выглядит так:
<?php
$file = fopen("example.txt", "r");
$contents = fread($file, filesize("example.txt"));
fclose($file);
echo $contents;Здесь fread() считывает до filesize("example.txt") байт — весь файл — в $contents. Для однострочного варианта file_get_contents() читает весь файл в строку без необходимости управлять дескриптором.
Обработка ошибок и отсутствующих файлов
fopen() возвращает false (и выдаёт предупреждение), если не может открыть файл — из-за неверных прав доступа, несуществующего каталога или диска только для чтения. Всегда проверяйте результат перед записью:
<?php
$file = fopen("/no/such/dir/example.txt", "w");
if ($file === false) {
echo "Could not open the file for writing.";
} else {
fwrite($file, "ok");
fclose($file);
}Перед чтением файла, не созданного в текущем запуске, убедитесь в его существовании с помощью file_exists(), чтобы избежать предупреждений от filesize() или fread().
Другие полезные файловые функции
Помимо создания и записи, PHP предоставляет полный набор инструментов для управления файлами:
file_get_contents()— читает весь файл в строку одним вызовом.file_put_contents()— записывает строку в файл одним вызовом.file_exists()— проверяет существование пути перед выполнением операций с ним.unlink()— удаляет файл.rename()— переименовывает или перемещает файл.copy()— копирует файл по новому пути.
Для файлов, загружаемых через форму, см. Загрузка файлов в PHP, а для общего представления об API файловой системы — Работа с файлами в PHP.
Итоги
- Открывайте файл с помощью
fopen($path, $mode); режим управляет поведением при создании, усечении или добавлении данных. - Используйте
"w"для перезаписи,"a"для добавления и"x", чтобы запретить перезапись существующего файла. fwrite()записывает данные, аfclose()сбрасывает буфер и освобождает дескриптор — всегда закрывайте его.- Для записи целой строки
file_put_contents()является лаконичной однострочной альтернативой. - Проверяйте возвращаемое значение
fopen()и используйтеfile_exists()для надёжного кода без предупреждений.