I am using Facebook Graph API to get contents from a Facebook fan page and then display them into a website. I am doing it like this, and it is working, but somehow, it seems that my hosting provider is limiting my requests every certain time.... So I would like to cache the response and only ask for a new request every 8h for example.
$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);
The get_data function uses CURL in the following way:
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;
}
This works fine, I can output the JSON data response and use it as I like into my website to display the content. But as I mention, in my hosting, this seems to fail every X time, I guess because I am getting limited. I have tried to cache the response using some code I saw here at Stackoverflow. But I cannot figure out how to integrate and use both codes. I have managed to create the cache file, but I cannot manage to read correctly from the cached file and avoid making a new request to Facebook graph API.
// 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;
Many thanks in advance for your help!
The Legacy REST API is in the process of being deprecated, while the Graph API is the most current, so if you're unsure of which one to use, your best bet is to go with that one. As you suggested, the Graph API, just like the Legacy REST API, is in fact a RESTful API.
The Graph API is named after the idea of a "social graph" — a representation of the information on Facebook. It's composed of nodes, edges, and fields.
Go to “My apps” drop down in the top right corner and select “add a new app”. Choose a display name and a category and then “Create App ID”. Again get back to the same link developers.facebook.com/tools/explorer. You will see “Graph API Explorer” below “My Apps” in the top right corner.
There are some thinks that could come in handy when trying to construct cache and to cache actual object (or even arrays).
The functions serialize
and unserialize
allows you to get a string representation of an object or of an array so you can cache it as plain text and then pop the object/array as it was before from the string.
filectime
which allows you to get the last modification date of a file, so when it is created, you can rely on this information to see if your cache is outdated like you tried to implement it.
And for the whole working code, there you go :
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 : note that I changed the $datos
variable on your actual function get_data
to a more common $data
.
This answer will add a few more dependencies to your project, but it may be well worth it instead of rolling your own stuff.
You could use the Guzzle HTTP client, coupled with the HTTP Cache plugin.
$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);
Not sure is you can use memcache, if you can:
$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
}
If your hosting provider is pushing all of your outbound requests through a proxy server -- you can try to defeat it by adding an extra parameter near the beginning of the request :
https://graph.facebook.com/12345678/posts?p=(randomstring)&access_token=1111112222233333&limit=20&fields=full_picture,link,message,likes,comments&date_format=U
I have used this successfully for outbound calls to third party data providers. Of course I don't know if your particular issue is this issue. You could also be bitten by the provider if they reject requests with parameters they don't expect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With