PHP 中的 5 分钟文件缓存
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5262857/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
5-minute file cache in PHP
提问by hyperknot
I have a very simple question: what is the best way to download a file in PHP but only if a local version has been downloaded more than 5 minute ago?
我有一个非常简单的问题:在 PHP 中下载文件的最佳方法是什么,但前提是本地版本已在 5 分钟前下载?
In my actual case I would like to get data from a remotely hosted csv file, for which I currently use
在我的实际情况下,我想从我目前使用的远程托管的 csv 文件中获取数据
$file = file_get_contents($url);
without any local copy or caching. What is the simplest way to convert this into a cached version, where the end result doesn't change ($file stays the same), but it uses a local copy if it's been fetched not so long ago (say 5 minute)?
没有任何本地副本或缓存。将其转换为缓存版本的最简单方法是什么,最终结果不会改变($file 保持不变),但如果它在不久前(比如 5 分钟)被获取,则它使用本地副本?
回答by Matt Gibson
Use a local cache file, and just check the existence and modification time on the file before you use it. For example, if $cache_file
is a local cache filename:
使用本地缓存文件,在使用前检查文件的存在和修改时间。例如,如果$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);
}
(Untested, but based on code I use at the moment.)
(未经测试,但基于我目前使用的代码。)
Either way through this code, $file ends up as the data you need, and it'll either use the cache if it's fresh, or grab the data from the remote server and refresh the cache if not.
无论通过这段代码的哪种方式, $file 最终都会作为您需要的数据,如果它是新鲜的,它将使用缓存,或者从远程服务器获取数据并刷新缓存,如果不是。
EDIT: I understand a bit more about file locking since I wrote the above. It might be worth having a read of this answerif you're concerned about the file locking here.
编辑:自从我写了上面的内容后,我对文件锁定有了更多的了解。如果您担心此处的文件锁定,可能值得阅读此答案。
If you're concerned about locking and concurrent access, I'd say the cleanest solution would be to file_put_contents to a temporaryfile, then rename()
it over $cache_file
, which should be an atomic operation, i.e. the $cache_file
will either be the old contents or the full new contents, never halfway written.
如果您担心锁定和并发访问,我会说最干净的解决方案是将 file_put_contents 到一个临时文件,然后rename()
它结束$cache_file
,这应该是一个原子操作,即$cache_file
要么是旧内容,要么是全新的内容,从来没有写到一半。
回答by Ken Le
Try phpFastCache, it support files caching, and you don't need to code your cache class. easy to use on shared hosting and VPS
试试phpFastCache,它支持文件缓存,你不需要编写你的缓存类。易于在共享主机和 VPS 上使用
Here is example:
这是示例:
<?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;
回答by Xeoncross
Here is a simple version which also passes a windows User-Agent
string to the remote host so you don't look like a trouble-maker without proper headers.
这是一个简单的版本,它也将一个 WindowsUser-Agent
字符串传递给远程主机,因此您看起来不会像没有正确标题的麻烦制造者。
<?php
function getCacheContent($cachefile, $remotepath, $cachetime = 120){
// Generate the cache version if it doesn't exist or it's 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);
}
回答by user470714
If you are using a database system of any type, you could cache this file there. Create a table for cached information, and give it at minimum the following fields:
如果您使用任何类型的数据库系统,您可以在那里缓存这个文件。为缓存信息创建一个表,并至少为其提供以下字段:
- An identifier; something you can use to retrieve the file the next time you need it. Probably something like a file name.
- A timestamp from the last time you downloaded the file from the URL.
- Either a path to the file, where it's stored in your local file system, or use a BLOB type field to just store the contents of the file itself in the database. I would recommend just storing the path, personally. If the file was very large, you definitely wouldn't want to put it in the database.
- 一个标识符;您可以在下次需要时使用它来检索文件。可能类似于文件名。
- 上次从 URL 下载文件的时间戳。
- 文件的路径,它存储在本地文件系统中,或者使用 BLOB 类型字段将文件本身的内容存储在数据库中。我个人建议只存储路径。如果文件非常大,您肯定不想将其放入数据库中。
Now, when you run the script above next time, first check in the database for the identifier, and pull the time stamp. If the difference between the current time and the stored timestamp is greater than 5 minutes pull from the URL and update the database. Otherwise, load the file from the database.
现在,下次运行上面的脚本时,首先在数据库中检查标识符,并提取时间戳。如果当前时间和存储的时间戳之间的差异大于 5 分钟,则从 URL 中提取并更新数据库。否则,从数据库加载文件。
If you don't have a database setup, you could do the same thing just using files, wherein one file, or field in a file, would contain the timestamp from when you last downloaded the file.
如果您没有数据库设置,您可以只使用文件来做同样的事情,其中一个文件或文件中的字段将包含您上次下载文件时的时间戳。
回答by Theon Lin
First, you might want to check the design pattern: Lazy loading.
首先,您可能需要检查设计模式:延迟加载。
The implementation should change to always load the file from local cache. If the local cache is not existed or file time jitter longer than 5 minute, you fetch the file from server.
实现应该更改为始终从本地缓存加载文件。如果本地缓存不存在或文件时间抖动超过 5 分钟,则从服务器获取文件。
Pseudo code is like following:
伪代码如下:
$time = filetime($local_cache)
if ($time == false || (now() - $time) > 300000)
fetch_localcache($url) #You have to do it yourself
$file = fopen($local_cache)
回答by alfmartinez
You can save a copy of your file on first hit, then check with filemtime the timestamp of the last modification of the local file on following hits.
您可以在第一次点击时保存文件的副本,然后使用 filemtime 在后续点击中检查本地文件最后修改的时间戳。
回答by powtac
You would warp it into a cache like method:
您可以将其变形为类似缓存的方法:
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;
}
回答by Peter M
I think you want some (psuedo code) logic like:
我想你想要一些(伪代码)逻辑,比如:
if ($file exists) {
if ($file time stamp older than 5 minutes) {
$file = file_get_contents($url)
}
} else {
$file = file_get_contents($url)
}
use $file