Работа с файлами — фундаментальный навык PHP-разработчика, открывающий двери к созданию динамических приложений, систем логирования, обработки данных и управления контентом. От простого чтения текстового файла до сложных операций с бинарными данными — PHP предлагает мощный, хотя и требующий аккуратности, инструментарий для взаимодействия с файловой системой.
Основные функции: от fopen() до fclose()
В основе работы с файлами в PHP лежит концепция дескрипторов. Вы не работаете с файлом напрямую, а получаете указатель (ресурс) на него с помощью функции fopen(). Это как получить ключ от комнаты — доступ есть, но после работы дверь нужно закрыть (fclose()).
Всегда закрывайте файлы с помощью fclose() после завершения работы. Это освобождает ресурсы системы и предотвращает потенциальные блокировки файла для других процессов.
Режимы открытия файла
Второй аргумент fopen() определяет, как мы будем работать с файлом:
- r — чтение (курсор в начале файла)
- r+ — чтение и запись (курсор в начале)
- w — запись (создаёт или очищает файл)
- a — добавление в конец (курсор в конце)
- x — эксклюзивное создание (ошибка, если файл существует)
Чтение файлов: несколько подходов
PHP предлагает разные методы чтения в зависимости от ваших нужд:
Построчное чтение
$handle = fopen("data.txt", "r");
while (!feof($handle)) {
$line = fgets($handle);
echo $line . "
";
}
fclose($handle);
Чтение всего файла сразу
Для небольших файлов удобны функции file_get_contents() (возвращает строку) и file() (возвращает массив строк).
Запись в файлы: от текста к данным
Запись осуществляется через fwrite() или file_put_contents(). Последняя особенно удобна для простых операций:
$data = "Новая запись\n";
file_put_contents("log.txt", $data, FILE_APPEND);
Используйте константу FILE_APPEND для добавления данных в конец файла вместо его перезаписи. Это критически важно для систем логирования.
Работа с директориями
PHP позволяет не только манипулировать файлами, но и навигацией по директориям:
scandir()— получает список файлов и папокmkdir()— создаёт директориюrmdir()— удаляет пустую директориюis_dir()/is_file()— проверяют тип
Безопасность — прежде всего!
Работа с файловой системой — одна из самых уязвимых точек в PHP-приложениях. Основные риски и их решение:
Проверка существования файла
Всегда проверяйте существование файла перед операциями: file_exists(), is_readable(), is_writable().
Защита от Path Traversal
Никогда не используйте пользовательский ввод напрямую в путях к файлам:
// ОПАСНО!
$file = $_GET['file']; // например, '../../etc/passwd'
// БЕЗОПАСНО
$baseDir = '/var/www/uploads/';
$file = basename($_GET['file']); // удаляет '../'
$path = $baseDir . $file;
if (strpos(realpath($path), $baseDir) === 0) {
// безопасный доступ
}
Блокировка файлов
При одновременном доступе из нескольких процессов используйте flock() для предотвращения конфликтов:
$fp = fopen("counter.txt", "r+");
if (flock($fp, LOCK_EX)) {
// эксклюзивная блокировка
$count = fread($fp, 10);
$count++;
ftruncate($fp, 0);
fwrite($fp, $count);
flock($fp, LOCK_UN); // снятие блокировки
}
fclose($fp);
Права доступа и CHMOD
Функция chmod() позволяет изменять права доступа к файлу. Помните о безопасных значениях:
- 755 для директорий и исполняемых файлов
- 644 для обычных файлов
- Никогда не используйте 777 в production!
Работа с CSV, JSON и сериализацией
PHP упрощает работу с популярными форматами:
// CSV
$rows = array_map('str_getcsv', file('data.csv'));
// JSON
$data = json_decode(file_get_contents('config.json'), true);
file_put_contents('config.json', json_encode($data, JSON_PRETTY_PRINT));
// Сериализация
$data = serialize($array);
file_put_contents('cache.dat', $data);
Производительность и лучшие практики
- Используйте
file_get_contents()/file_put_contents()для простых операций - Для больших файлов используйте потоковое чтение (
fgets()в цикле) - Кэшируйте часто читаемые файлы в памяти
- Используйте абсолютные пути вместо относительных
- Всегда обрабатывайте ошибки с помощью
try-catchили проверок
FAQ: Часто задаваемые вопросы
Как прочитать файл построчно?
Используйте комбинацию fopen(), feof() и fgets() в цикле, либо функцию file(), которая возвращает массив строк.
Как безопасно получить содержимое файла по имени от пользователя?
Никогда не доверяйте пользовательскому вводу. Используйте basename() для очистки имени, проверяйте допустимые расширения и храните файлы вне корневой директории веб-сервера.
В чём разница между file_get_contents() и fopen()?
file_get_contents() читает весь файл в строку сразу, что удобно для небольших файлов. fopen() с последующим чтением даёт больше контроля и эффективна для больших файлов.
Как добавить текст в конец файла?
Используйте file_put_contents() с флагом FILE_APPEND или откройте файл в режиме "a" через fopen() и запишите через fwrite().
Как удалить файл?
Функция unlink() удаляет файл. Всегда проверяйте существование файла и права доступа перед удалением.
Как создать директорию со всеми родительскими папками?
Используйте mkdir() с третьим параметром true: mkdir('/path/to/new/dir', 0755, true).