Как на PHP реализовать простую систему кэширования результатов тяжелых SQL-запросов в файлы?

Файловое кэширование — один из самых простых и эффективных способов снизить нагрузку на базу данных в PHP-приложениях. Идея проста: результат тяжёлого SQL-запроса сохраняется в файл, и при следующем обращении данные читаются из файла, а не из БД, пока не истечёт время жизни кэша (TTL).

## Базовый принцип работы

1. Генерируем уникальный ключ кэша на основе SQL-запроса (например, md5 от строки запроса).
2. Проверяем, существует ли файл кэша и не устарел ли он.
3. Если кэш актуален — читаем данные из файла.
4. Если кэша нет или он устарел — выполняем запрос к БД, сохраняем результат в файл.

## Пример реализации

php
function queryWithCache(PDO $pdo, string $sql, array $params = [], int $ttl = 3600): array {
$cacheDir = __DIR__ . ‘/cache/’;
if (!is_dir($cacheDir)) {
mkdir($cacheDir, 0755, true);
}

$cacheKey = md5($sql . serialize($params));
$cacheFile = $cacheDir . $cacheKey . ‘.cache’;

// Проверяем актуальность кэша
if (file_exists($cacheFile) && (time() — filemtime($cacheFile)) prepare($sql);
$stmt->execute($params);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Сохраняем результат в файл
file_put_contents($cacheFile, serialize($result));

return $result;
}

## Пример использования

php
$pdo = new PDO(‘mysql:host=localhost;dbname=mydb’, ‘user’, ‘password’);

$sql = ‘SELECT * FROM products WHERE category_id = :cat ORDER BY rating DESC LIMIT 100’;
$products = queryWithCache($pdo, $sql, [‘:cat’ => 5], 1800);

## Важные рекомендации

**Безопасность:** Не храните кэш в публично доступных директориях (например, внутри `public_html`). Разместите папку `cache/` выше корня веб-сервера или закройте её через `.htaccess`.

**Инвалидация кэша:** При изменении данных в таблице нужно удалять соответствующие файлы кэша. Для этого можно использовать теги кэша или просто очищать всю папку при записи.

**Атомарность записи:** Чтобы избежать гонки потоков, используйте запись во временный файл с последующим переименованием:
php
$tmpFile = $cacheFile . ‘.tmp’;
file_put_contents($tmpFile, serialize($result));
rename($tmpFile, $cacheFile);

**Очистка устаревших файлов:** Периодически запускайте скрипт, удаляющий файлы старше определённого времени, чтобы не засорять диск.

**Альтернативы:** Для высоконагруженных проектов рассмотрите Redis или Memcached — они быстрее файловой системы и поддерживают автоматическое удаление устаревших записей.

Файловое кэширование отлично подходит для небольших и средних проектов, где нет возможности использовать in-memory хранилища, но нужно существенно снизить количество запросов к базе данных.


Задайте вопрос нейросети

Не нашли ответ? Спросите ИИ — он подготовит развёрнутую статью.