Кэширование API-графика Google Graph API JSON
Я использую API-интерфейс Facebook, чтобы получить содержимое с страницы поклонника Facebook, а затем отобразить их на веб-сайте. Я делаю это так, и он работает, но почему-то кажется, что мой хостинг-провайдер ограничивает мои запросы каждый определенный момент... Поэтому я хотел бы кэшировать ответ и запрашивать новый запрос каждые 8 часов для пример.
$data = get_data("https://graph.facebook.com/12345678/posts?access_token=1111112222233333&limit=20&fields=full_picture,link,message,likes,comments&date_format=U");
$result = json_decode($data);
Функция get_data использует CURL следующим образом:
function get_data($url) {
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$datos = curl_exec($ch);
curl_close($ch);
return $datos;
}
Это отлично работает, я могу вывести ответ данных JSON и использовать его, как мне нравится, на своем веб-сайте для отображения содержимого. Но, как я уже упоминал, на моем хостинге это, похоже, терпит неудачу каждый X раз, я думаю, потому что я ограничусь. Я попытался кэшировать ответ, используя код, который я видел здесь, в Stackoverflow. Но я не могу понять, как интегрировать и использовать оба кода. Мне удалось создать файл кеша, но я не могу правильно читать из кэшированного файла и не вносить новый запрос в графический API Facebook.
// cache files are created like cache/abcdef123456...
$cacheFile = 'cache' . DIRECTORY_SEPARATOR . md5($url);
if (file_exists($cacheFile)) {
$fh = fopen($cacheFile, 'r');
$cacheTime = trim(fgets($fh));
// if data was cached recently, return cached data
if ($cacheTime > strtotime('-60 minutes')) {
return fread($fh);
}
// else delete cache file
fclose($fh);
unlink($cacheFile);
}
$fh = fopen($cacheFile, 'w');
fwrite($fh, time() . "\n");
fwrite($fh, $json);
fclose($fh);
return $json;
Большое спасибо за вашу помощь!
Ответы
Ответ 1
Есть некоторые мысли, которые могут пригодиться при попытке создать кеш и кэшировать фактический объект (или даже массивы).
Функции serialize
и unserialize
позволяют получить строковое представление объекта или массива, поэтому вы можете кэшировать его как обычный текст, а затем всплывать объект/массив, как и раньше, из строки.
filectime
, который позволяет вам получить последнюю дату изменения файла, поэтому, когда она создана, вы можете полагаться на эту информацию, чтобы узнать, есть ли ваш кеш устарел, как вы пытались его реализовать.
И для всего рабочего кода вы идете:
function get_data($url) {
/** @var $cache_file is path/to/the/cache/file/based/on/md5/url */
$cache_file = 'cache' . DIRECTORY_SEPARATOR . md5($url);
if(file_exists($cache_file)){
/**
* Using the last modification date of the cache file to check its validity
*/
if(filectime($cache_file) < strtotime('-60 minutes')){
unlink($cache_file);
} else {
echo 'TRACE -- REMOVE ME -- out of cache';
/**
* unserializing the object on the cache file
* so it gets is original "shape" : object, array, ...
*/
return unserialize(file_get_contents($cache_file));
}
}
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$data = curl_exec($ch);
curl_close($ch);
/**
* We actually did the curl call so we need to (re)create the cache file
* with the string representation of our curl return we got from serialize
*/
file_put_contents($cache_file, serialize($data));
return $data;
}
PS: обратите внимание, что я изменил переменную $datos
на вашу фактическую функцию get_data
на более общий $data
.
Ответ 2
Этот ответ добавит еще несколько зависимостей к вашему проекту, но, возможно, это стоит того, чтобы переводить ваши собственные вещи.
Вы можете использовать Guzzle HTTP-клиент в сочетании с HTTP Cache.
$client = new Client('http://www.test.com/');
$cachePlugin = new CachePlugin(array(
'storage' => new DefaultCacheStorage(
new DoctrineCacheAdapter(
new FilesystemCache('/path/to/cache/files')
)
)
));
$client->addSubscriber($cachePlugin);
$request = $client->get('https://graph.facebook.com/12345678/posts?access_token=1111112222233333&limit=20&fields=full_picture,link,message,likes,comments&date_format=U');
$request->getParams()->set('cache.override_ttl', 3600*8); // 8hrs
$data = $request->send()->getBody();
$result = json_decode($data);
Ответ 3
Не уверен, что вы можете использовать memcache, если можете:
$cacheFile = 'cache' . DIRECTORY_SEPARATOR . md5($url);
$mem = new Memcached();
$mem->addServer("127.0.0.1", 11211);
$cached = $mem->get($cacheFile);
if($cached){
return $cached;
}
else{
$data = get_data($url);
$mem->set($cacheFile, json_encode($data), time() + 60*10); //10 min
}
Ответ 4
Если ваш хостинг-провайдер перенаправляет все ваши исходящие запросы через прокси-сервер - вы можете попытаться победить его, добавив дополнительный параметр рядом с началом запроса:
https://graph.facebook.com/12345678/posts?p=(randomstring)&access_token=1111112222233333&limit=20&fields=full_picture,link,message,likes,comments&date_format=U
Я успешно использовал это для исходящих вызовов сторонних поставщиков данных. Конечно, я не знаю, является ли ваша проблема проблемой. Вы также можете укусить провайдера, если они отклонят запросы с параметрами, которые они не ожидают.