How to cache facebook graph api call - php

I've created a function to get the likes for my facebook page using the graph api. However, the level rate limit keeps on getting reached as it's being called on every request.
How would i cache this so it doesn't make the call every time?
The code i'm currently using is:
function fb_like_count() {
$id = '389320241533001';
$access_token = 'access token goes here';
$json_url ='https://graph.facebook.com/v3.2/'.$id.'?fields=fan_count&access_token='.$access_token;
$json = file_get_contents($json_url);
$json_output = json_decode($json);
if($json_output->fan_count) {
return like_count_format($json_output->fan_count);
} else{
return 0;
}
}

There are many cache mechanism in PHP that you can use depending on your project size.
I would suggest you to check memcached or Redis. These are in-memory cache mechanisms that are pretty fast and would help you to gain better performance.
You can read more about how to implement memcached here or for redis here.
The second and easier way is to use file caching. It works like this:
You send a request to Facebook API and when response is returned you save it to a file. When you want to send the second response you can check if there is any content in your file first and if there is you can return that directly to your application otherwise you will send the request to Facebook API
Simple integration is like this
if (file_exists($facebook_cache_file) && (filemtime($facebook_cache_file) > (time() - 60 * 15 ))) {
// Cache file is less than 15 minutes old but you can change this.
$file = file_get_contents($facebook_cache_file); // this holds the api data
} 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.
$response = getFacebookData() // get data from facebook and save into file
file_put_contents($facebook_cache_file, $response, LOCK_EX);
}
Anyway I would suggest you to use any PHP library for doing file cache.
Below you can find some that might be interesting to look at:
https://github.com/PHPSocialNetwork/phpfastcache
https://symfony.com/doc/current/components/cache.html

Related

Google API request every 30 seconds

I'm using Live Reporting Google APIs to retrieve active users and display the data inside a mobile application. On my application I'd like to make a HTTP request to a PHP script on my server which is supposed to return the result.
However I read on Google docs that it's better not to request data using APIs more often than 30 seconds.
I prefer not to use a heavy way such as a cron job that stores the value inside my database. So I'd like to know if there's a way to cache the content of my PHP scrpit na dmake it perform an API request only when the cache expires.
Is there any similar method to do that?
Another way could be implementing a very simple cache by yourself.
$googleApiRequestUrlWithParameter; //This is the full url of you request
$googleApiResponse = NULL; //This is the response by the API
//checking if the response is present in our cache
$cacheResponse = $datacache[$googleApiRequestUrlWithParameter];
if(isset($cacheResponse)) {
//check $cacheResponse[0] for find out the age of the cached data (30s or whatever you like
if(mktime() - $cacheResponse[0] < 30) {
//if the timing is good
$googleApiResponse = $cacheResponse[1];
} else {
//otherwise remove it from your "cache"
unset($datacache[$googleApiRequestUrlWithParameter]);
}
}
//if you do no have the response
if(!isset($googleApiResponse)) {
//make the call to google api and put the response in $googleApiResponse then
$datacache[] = array($googleApiRequestUrlWithParameter => array(mktime(), $googleApiResponse)
}
If you data are related to the user session, you could store $datacahe into $_SESSION
http://www.php.net/manual/it/reserved.variables.session.php
ortherwise define $datacache = array(); as a global variable.
There is a lot of way of caching things in PHP, the simple/historic way to manage cache in PHP is with APC http://www.php.net/manual/book.apc.php
Maybe I do not understard correctly your question.

Instagram max requests per hour (30) exceeded?

{
"code":420,
"error_type":"OAuthRateLimitException",
"error_message":"You have exceeded the maximum number of requests per hour. You have performed a total of 253 requests in the last hour. Our general maximum request limit is set at 30 requests per hour."
}
I just noticed a clients website I am looking after has stopped showing the Instagram feed, so I loaded up the feed URL straight into the browser and I got the above error. I don't think there should have been 253 requests in an hour, but whilst Googling this problem, I came across someone saying it was because the API was being logged in on every request. Sadly, I have "inherited" this code, and haven't really worked with the Instagram API before, apart from to fix an error with this same website before.
The clients site is in WordPress so I have wrapped the code to get the images in a function:
function get_instagram($user_id=USERID,$count=6,$width=190,$height=190){
$url = 'https://api.instagram.com/v1/users/'.$user_id.'/media/recent/?access_token=ACCESSTOKEN&count='.$count;
// Also Perhaps you should cache the results as the instagram API is slow
$cache = './'.sha1($url).'.json';
if(file_exists($cache) && filemtime($cache) > time() - 60*60){
// If a cache file exists, and it is newer than 1 hour, use it
$jsonData = json_decode(file_get_contents($cache));
} else {
$jsonData = json_decode((file_get_contents($url)));
file_put_contents($cache,json_encode($jsonData));
}
$result = '<a style="background-image:url(/wp-content/themes/iwear/inc/img/instagram-background.jpg);" target="_BLANK" href="http://www.instagr.am" class="lc-box lcbox-4 instagram">'.PHP_EOL.'<ul>'.PHP_EOL;
foreach ($jsonData->data as $key=>$value) {
$result .= "\t".'<li><img src="'.$value->images->low_resolution->url.'" alt="'.$value->caption->text.'" data-width="'.$width.'" data-height="'.$height.'" /><div class="lc-box-inner"><div class="title"><h2>images</h2></div><div class="description">'.$value->caption->text.'</div></div></li>'.PHP_EOL;
}
$result .= '</ul></a>'.PHP_EOL;
return $result;
}
But as I said, this code has stopped working. Is there any way I could optimize this to actually work? I also notice there is mention of a cache in the (probably stolen) instagram stuff, but it isn't actually caching, so that could also be a solution
Thanks
Try registering a new client in instagram and then change
$url = 'https://api.instagram.com/v1/users/'.$user_id.'/media/recent/?access_token=ACCESSTOKEN&count='.$count;
for
$url = https://api.instagram.com/v1/users/'.$user_id.'/media/recent/?client_id=CLIENT_ID&count='.$count;
where CLIENT_ID is the client id of your recently created client.

Facebook Friends Count?

What is the best way to count a Facebook user's friends...
I'm currently using (PHP):
$data = $facebook->api('/me/friends');
$friends_count = count($data['data']);
and its very slow... (about 2 secs)
Querying the facebook api sends a request to facebook. Because its a common http-request this Probably takes most of the time. There is usually no way around it. If you need the values more often, you should cache them somewhere
if (file_exists($cacheFile)) {
$data = file_get_contents($cachefile);
} else {
$data = $facebook->api('/me/friends');
file_put_contents($cacheFile, $data);
}
$friends_count = count($data['data']);
Remember to update the cache file from time to time.
If you are not processing the data given by Facebook on server side, instead of doing it using PHP, you can use JavaScript graph API to fetch, it can fetch it using ajax which wont effect your page load time.

Resin Session in Google App Engine

I'm developing on GAE using Resin, it seems that my PHP session on the production site is short lived and doesn't get updated (i.e., making requests doesn't seem to increase it's expiry period). Local is fine, as long as I don't close the tab, the session persists.
Any pointer on this? My users are getting frustrated as they are kicked very frequently :(
I think the code is the best tutorial :)
// global mem cache service handle
$MEM_CACHE_SERVICE = NULL;
// table to store session like information
$MY_SESSION_TABLE = array();
function load_mcache($key) {
global $MEM_CACHE_SERVICE;
if (!$MEM_CACHE_SERVICE) {
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.api.memcache.Expiration;
$MEM_CACHE_SERVICE = MemcacheServiceFactory::getMemcacheService();
}
return $MEM_CACHE_SERVICE->get($key);
}
function save_mcache($key, $value, $cache_time) {
global $MEM_CACHE_SERVICE;
if (!$MEM_CACHE_SERVICE) {
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.api.memcache.Expiration;
$MEM_CACHE_SERVICE = MemcacheServiceFactory::getMemcacheService();
}
$expiration = Expiration::byDeltaSeconds($cache_time);
return $MEM_CACHE_SERVICE->put($key, $value, $expiration);
}
// unserializing array from mem cache
// if nothing found like first time and after a minute, then add key to the table
if (!($MY_SESSION_TABLE = unserialize(load_mcache($_REQUEST['JSESSIONID'])))) {
// save something to cache on first page load because we didnt have anything
$MY_SESSION_TABLE['key1'] = date('m/d/Y H:i:s');
// using jsessionid as a mem cache key, serializing array and setting cache time to one minute
save_mcache($_REQUEST['JSESSIONID'], serialize($MY_SESSION_TABLE), 60);
}
// now my session table is available for a minute until its initialized again
print_r($MY_SESSION_TABLE);
Now for proper session functionality you need to add set and get methods or even better a small class for handling it. Little abstraction to the classes and you could choose what kind of session mechanism to use with same library on different web app scenarios.

PHP function to get Facebook status?

I'm looking for a good, simple PHP function to get my latest Facebook status updates. Anyone know of one?
Thanks!
EDIT: I've added a half-solution below.
Or if anyone knows a good way to read in the RSS feed and spit out the recent status update?
A quick check on PEAR found Services_Facebook
This is an incomplete answer, but this is what I've gotten so far:
First: add the developer application on FB. Then create a new application. Call it whatever you want.
Second: Download the PHP client. Dump it somewhere on your webhost, i.e. /facebook/
Third: Copy the following beginner code to get yourself started into a php file:
<?php
require_once('facebook/php/facebook.php');
$facebook = new Facebook("YOUR_API_KEY","YOUR_SECRET_KEY");
$result = $facebook->api_client->fql_query("SELECT status FROM user WHERE uid = YOURIDNUMBER");
// OR --- they both get the same data
$result = $facebook->api_client->users_getInfo(YOURIDNUMBER,'status');
print_r($result);
echo "<pre>Debug:" . print_r($facebook,true) . "</pre>"; // debug info
?>
Other info:
You must be logged in and have the
application added. OR you give the
application offline_access
permissions and have the
aapplication added.
You can add offline_access by typing
in the following url:
http://www.facebook.com/authorize.php?api_key=YOUR_API_KEY&v=1.0&ext_perm=offline_access
more info on permissions found here: http://wiki.developers.facebook.com/index.php/Extended_permissions
I'm at a stopping point: anything my
program calls the fql query or
users_getInfo, my page stops
executing the php? I'm guessing
there are a limited amount of calls
for new applications? I've never
done any FB development so I'm
completely new to it. Maybe make
the call and save your recent status
(or most recent statuses) in your
own DB to prevent excessive calls to
the API?
I hope this helps someone get started!
EDIT: It seems that FB won't let you access someones status, even if the offline_access is on, unless you are that person or their friend (depending on their privacy settings).
I did however, finally manage to find the RSS feed in the new profile version: http://www.new.facebook.com/minifeed.php?filter=11
I have found a way to fetch your latest facebook status. This is how you do it:
1) Create a facebook app, and copy your application secret and application id.
2) Grant the app read_stream and offline_access to your profile. (http://developers.facebook.com/docs/authentication/permissions) To fetch your latest status the app needs an access_token. With offline_access granted the access_token should "never" expire. The easiest way to do this is to click the button generated by this code: (be sure to fill in 'your app id' and set cookie to true!)
<fb:login-button perms="read_stream,offline_access"></fb:login-button>
<div id="fb-root"></div>
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script>FB.init({appId: 'your app id', status: true, cookie: true, xfbml: true});</script>
3) Now try to find out what access_token it is using. The access_token is saved in the fbs_appId cookie. Locate it using your browser or using $_COOKIE['fbs_appId']. Look for access_token=....
4) Now that you have a (hopefully) never expiring access_token you can use the following code:
$access_token='xxxxxxxxxxxxxxxxxxxx';
$appId='123456789132456789';
$appSecret='xxxxxxxxxxxxxxxxxxxx';
$profileId='123456789';
//http://github.com/facebook/php-sdk/blob/master/src/facebook.php
require 'facebook.php';
$facebook = new Facebook(array('appId' => $appId,'secret' => $appSecret));
$response = $facebook->api('/'.$profileId.'/feed?limit=1&access_token='.$access_token);
5) The message part should be located: $response['data'][0]['message']
I don't know HOW long the access token is valid. Facebook says:
Enables your application to perform authorized requests on behalf of the user at any time. By default, most access tokens expire after a short time period to ensure applications only make requests on behalf of the user when the are actively using the application. This permission makes the access token returned by our OAuth endpoint long-lived.
Here is a REALLY simple function if you just want to get the latest status. It doesn't depend on the Facebook SDK or anything. You just need CURL and JSON support.
Simple PHP function to get facebook status
I never seem to get along with PEAR, but if you have better luck than I, then the PEAR solution seems the best route long term.
Another idea is to explore the Facebook Developer API library and see if that might give you anything you are looking for.
Lastly, there used to be a way to get an RSS feed... but I can't seem to find any instructions that work anymore, but you might poke around Facebook help if that interests you. Mine ends up looking something like this:
http://www.new.facebook.com/feeds/status.php?id=[idnumber]&viewer=[viewer]&key=[key]&format=rss20
I got it working using Jens' post to retrieve a valid access_token. Then, I extracted the status messages and the time of posting from the xml file using the following code (you can change $limit to display more or less status messages, or use a form to change it).
Be sure to put in your Facebook ID and the access token you got from the app you created (see Jens' post). You can check the output of this script here.
Have fun!
<?php
if(isset($_POST['limit'])) {
$limit = $_POST['limit'];
}
else {
$limit = 3; // number of status messages to display
}
$f = fopen ("https://api.facebook.com/method/status.get?uid=YOUR_FACEBOOK_ID&limit=".$limit."&access_token=YOUR_ACCESS_TOKEN", "r");
while ($line= htmlentities(fgets($f))) {
if ($line===FALSE) print ("FALSE\n");
else
{
$content = $content." ".$line;
}
}
fclose ($f);
$message = explode("<message>", $content); // search for the <message> tag
$message_cnt = count($message);
$msg_index = 0;
$time = explode("<time>", $content); // search for the <time> tag
for($i=1; $i<$message_cnt; $i++)
{
$tmp = explode("</message&gt", $message[$i]);
$msg[$msg_index] = $tmp[0]; // status message
$tmp2 = explode("</time&gt", $time[$i]);
$t[$msg_index++] = $tmp2[0]; // time of posting
}
for($i=0; $i<$msg_index; $i++)
{
echo("<span class=\"status\">".preg_replace('!\015\012|\015|\012!','<br>',$msg[$i])."</span><br>\n
<span class=\"date\">on ".date("d.m.Y", $t[$i])." at ".date("H:i",$t[$i])."</span><br><br>\n");
}
?>
I have tried loads of tutorials over the last few days and none of them have worked. I think it may be due to facebook changing their api requirements. This is the only one I found that works at the moment:
http://www.deanblog.co.uk/article/13/adding-a-facebook-status-feed-to-your-website-with-php
Just use PHPforFB framework (www.phpforfb.com/en/) for the fastest way.
The code looks like this:
require_once('phpforfb_framework.php');
$structInit = array('app_id' => APP_ID,'app_name' => APP_NAME,'sec_key' => APP_SECKEY);
$FacebookAPP = new PHPforFB($structInit);
if($FacebookAPP->lastErrorCode>0){
//Creation failed => Display error message and exit
echo "PHPforFB Error: ".$FacebookAPP->lastErrorCode." -> ".$FacebookAPP->lastError;
}else{
//PHPforFB framework established
if($FacebookAPP->userLoggedIn === TRUE){
//If the user is logged in at Facebook:
//Here you can determine if the user has at least once before
//granted basic permissions to your application.
if($FacebookAPP->userAuthenticated === FALSE){
//The user has not yet granted permissions
//**your code here**
}else{
//The user has already granted permissions, therefore his Facebook ID
//is known to us. It is always available in $FacebookAPP->userID:
$userID = $FacebookAPP->userID;
//**your code here**
}
}
}
Since I couldn't use the API route, I went with the RSS found at: http://www.new.facebook.com/minifeed.php?filter=11
And used the following PHP function, called StatusPress, with some of my own modifications, to parse the RSS feed for my Facebook status. Works great!
<?php
// see http://github.com/facebook/php-sdk/blob/master/facebook.php
require './facebook.php';
// Create our Application instance.
// see http://www.youtube.com/watch?v=jYqx-RtmkeU for how to get these numbers
$facebook = new Facebook(array('appId' => 'XXX','secret' => 'XXX'));
// This call will always work since we are fetching public data.
// this could be /username or /username/friends etc...
// see developer api for FQL for examples
$status = $facebook->api('/haanmc/feed?limit=1');
?>
<p><?php print $status['data'][0]['message']; ?></p>
<p>Likes: <?php print $status['data'][0]['likes']; ?> | Comments: <?php print count($status['data'][0]['comments']['data']); ?></p>
<textarea style="width: 95%; height: 600px;"><?php print_r($status); ?></textarea>

Categories