Мастер файлов: Полное руководство по работе с файлами в PHP от чтения до безопасности

Мастер файлов: Полное руководство по работе с файлами в PHP от чтения до безопасности

Работа с файлами — фундаментальный навык 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);

Производительность и лучшие практики

  1. Используйте file_get_contents()/file_put_contents() для простых операций
  2. Для больших файлов используйте потоковое чтение (fgets() в цикле)
  3. Кэшируйте часто читаемые файлы в памяти
  4. Используйте абсолютные пути вместо относительных
  5. Всегда обрабатывайте ошибки с помощью 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).