«
»

Facebook, PHP, Tips

Workaround to Facebook’s Graph API Search locale change

01.30.13 | 5 Comments

No Gravatar

So Facebook decided to change the meaning of the locale parameter to the search parts of the Graph API – and label the decision “by design” after 2 months of thinking. Not “design change” or “bug we don’t feel like fixing” – just “If it worked before – that was a mistake”. The handling of the problem is described in this bug-report.

If you do not use it, you probably don’t care, but if you do this would probably be fatal to your searches.

The problem

I would like to know what Facebook users in my country (Denmark) writes about my local branch of the phone company Telia. To find out, I would ask the graph:

https://graph.facebook.com/search?q=Telia&locale=da_DK

The locale-parameter would ensure that I only get results from danish Facebook sources. At least that was the case until December 5, 2012. After that, the locale-parameter changed role – now it will just localize certain field identifiers in the JSON reply. This is useless and all of a sudden I get heaps of irrelevant results from users in other countries in other languages. Facebook remains silent about what to do instead.

The workaround

For my projects I’ve used the following workaround – it’s Q&D, ugly and it takes up unnecessary resources, both for my own service and for Facebook, but it has been tested to work. One known drawback – if the same Facebook user mentions our search term more than once, only the last one is returned.

First – perform the search as always – in simple PHP (make sure to add your own validations):

<?php
$searchterm = 'telia';
$geturl = "http://graph.facebook.com/search?q=" . urlencode($searchterm) . "&type=post";
$fb_reply = file_get_contents($geturl, 0, null, null);
$fb_arr = json_decode($fb_reply, TRUE);
$reply_data = $fb_arr['data'];

Now $reply_data contains an array of posts – something like:

Array
(
 [0] => Array
 (
   [id] => 10002333417237_486897434763199
   [from] => Array
   (
     [name] => some name
     [id] => 100027398117237
   )
  [message] => Missing home
...

Look at the [from]-section to figure out who posted the message. Actually you are going to need all the from->id’s from all posts in the reply from Facebook. Why? Because you want to extract the senders locale and filter out any posts that does not match the locale you require. I use something like this to create an array of Facebook uid’s:

$users = array();
foreach ($reply_data as $pkey => $post) {
 $uid = $post['from']['id'];
 $users[$uid] = $pkey;
}

Next we ask Facebook about the users using FQL. Actually we only want to know about users if they have our locale:

$FQL = sprintf("SELECT uid, name, locale FROM user WHERE uid IN (%s) AND locale = 'da_DK';", implode(array_keys($users), ','));
$fql_query = "http://graph.facebook.com/fql?q=" . urlencode($FQL);
$fql_result = file_get_contents($fql_query, 0, null, null);
$fql_users = json_decode($fql_result, TRUE);

Now $users is a one-to-one mapping from users to matching posts, we’ll “join” the filtered user list with the $users-array and have – a list of posts from users with the requested locale:

$valid_posts = array();
foreach($fql_users['data'] as $dk_user) {
 $uid = $dk_user['uid'];
 $postkey = $users[$uid];
 $valid_posts[] = $reply_data[$postkey];
}

The $valid_posts-array now contains posts matching the needed locale – somewhat like before December 5th 2012.

Conclusion

I wonder why Facebook took the decision they did. It is just asking for workarounds like this. Now instead of one Facebook Graph request I will make two AND Facebook gets to send me a lot more data than I need. The data is still public (for now anyway) – let’s see if it stays that way.

5 Comments

have your say

Add your comment below, or trackback from your own site. Subscribe to these comments.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

:

:


«
»