5-минутный кэш файлов в PHP
У меня очень простой вопрос: какой лучший способ загрузить файл на PHP, но только если локальная версия была загружена более 5 минут назад?
В моем фактическом случае я хотел бы получить данные из удаленно размещенного csv файла, для которого в настоящее время я использую
$file = file_get_contents($url);
без локальной копии или кеширования. Каков самый простой способ преобразовать это в кешированную версию, где конечный результат не изменяется (файл $остается таким же), но он использует локальную копию, если она была получена не так давно (скажем, 5 минут)?
Ответы
Ответ 1
Используйте локальный файл кеша и просто проверяйте время существования и модификации файла перед его использованием. Например, если $cache_file
- это имя файла локального кэша:
if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 60 * 5 ))) {
// Cache file is less than five minutes old.
// Don't bother refreshing, just use the file as-is.
$file = file_get_contents($cache_file);
} else {
// Our cache is out-of-date, so load the data from our remote server,
// and also save it over our cache for next time.
$file = file_get_contents($url);
file_put_contents($cache_file, $file, LOCK_EX);
}
(Непроверенный, но на основе кода, который я использую в данный момент.)
В любом случае с помощью этого кода файл $заканчивается как данные, которые вам нужны, и он будет использовать кеш, если он свежий, или захватить данные с удаленного сервера и обновить кеш, если нет.
EDIT: Я понимаю немного больше о блокировке файлов, так как я написал выше. Возможно, стоит прочитать этот ответ, если вас беспокоит блокировка файла здесь.
Если вы обеспокоены блокировкой и одновременным доступом, я бы сказал, что самым чистым решением будет файл_put_contents во временный файл, затем rename()
it над $cache_file
, который должен быть атомной операцией, т.е. $cache_file
будет либо старым содержимым, либо полным новым содержимым, никогда не написанным на полпути.
Ответ 2
Попробуйте phpFastCache, он поддерживает кеширование файлов, и вам не нужно кодировать свой класс кеша. простой в использовании на общем хостинге и VPS
Вот пример:
<?php
// change files to memcached, wincache, xcache, apc, files, sqlite
$cache = phpFastCache("files");
$content = $cache->get($url);
if($content == null) {
$content = file_get_contents($url);
// 300 = 5 minutes
$cache->set($url, $content, 300);
}
// use ur $content here
echo $content;
Ответ 3
Если вы используете систему баз данных любого типа, вы можете кэшировать этот файл там. Создайте таблицу для кешированной информации и дайте ей минимум следующие поля:
- Идентификатор; что вы можете использовать для получения файла в следующий раз, когда вам это нужно. Возможно, что-то вроде имени файла.
- Временная метка с момента последнего загрузки файла из URL-адреса.
- Либо путь к файлу, где он хранится в локальной файловой системе, либо поле типа BLOB, чтобы просто сохранить содержимое самого файла в базе данных. Я бы рекомендовал просто сохранить путь лично. Если файл был очень большой, вы определенно не захотели бы поместить его в базу данных.
Теперь, когда вы запустите script в следующий раз, сначала проверьте базу данных для идентификатора и потяните отметку времени. Если разница между текущим временем и сохраненной меткой времени превышает 5 минут, вытащите URL-адрес и обновите базу данных. В противном случае загрузите файл из базы данных.
Если у вас нет настройки базы данных, вы можете сделать то же самое, просто используя файлы, в которых один файл или поле в файле будет содержать метку времени при последнем скачивании файла.
Ответ 4
Сначала вы можете проверить шаблон дизайна: Lazy loading.
Реализация должна измениться, чтобы всегда загружать файл из локального кеша.
Если локальный кеш не существует или дрожит время файла более 5 минут, вы извлекаете файл с сервера.
Псевдокод выглядит следующим образом:
$time = filetime($local_cache)
if ($time == false || (now() - $time) > 300000)
fetch_localcache($url) #You have to do it yourself
$file = fopen($local_cache)
Ответ 5
Вот простая версия, которая также передает строку windows User-Agent
на удаленный хост, чтобы вы не выглядели как создатели проблем без соответствующих заголовков.
<?php
function getCacheContent($cachefile, $remotepath, $cachetime = 120){
// Generate the cache version if it doesn't exist or it too old!
if( ! file_exists($cachefile) OR (filemtime($cachefile) < (time() - $cachetime))) {
$options = array(
'method' => "GET",
'header' => "Accept-language: en\r\n" .
"User-Agent: Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)\r\n"
);
$context = stream_context_create(array('http' => $options));
$contents = file_get_contents($remotepath, false, $context);
file_put_contents($cachefile, $contents, LOCK_EX);
return $contents;
}
return file_get_contents($cachefile);
}
Ответ 6
Вы можете сохранить копию своего файла при первом попадании, а затем проверить с filemtime метку времени последней модификации локального файла при следующих хитах.
Ответ 7
Вы деформируете его в кеш, как метод:
function getFile($name) {
// code stolen from @Peter M
if ($file exists) {
if ($file time stamp older than 5 minutes) {
$file = file_get_contents($url)
}
} else {
$file = file_get_contents($url)
}
return $file;
}
Ответ 8
Я думаю, вам нужна какая-то (psuedo-код) логика вроде:
if ($file exists) {
if ($file time stamp older than 5 minutes) {
$file = file_get_contents($url)
}
} else {
$file = file_get_contents($url)
}
use $file