As I said before, I've had some trouble with PHP Facebook development.. This time, I couldn't get a user ID because the user came from a non-Facebook page.
An application's drawing page is called it's "canvas page". It's the starting point for the whole app. Unfortunately, when the user jumps there from a bookmark, or enters the URL into the browser directly, Facebook can't supply the user ID. The app can't do anything, because it doesn't know who the heck it's working for. The user must visit your app's canvas page from a Facebook page.
Since your canvas page is a Facebook page, and the user just visited it directly, you'd think that redirecting to the same page would do the job. And it does! But only if the user clicks on a link.
Then there's the additional problem of users who don't allow you to see their user ID. You have to ask them for permission first.
I put together a skeleton that takes care of all these issues for FBML pages (I don't think it'll work for iFrame pages). Read on for the code.
First, we need to include some variables. For instance, you'll need to know your Facebook app id, API key, and secret. (I call these $fbappid, $fbapikey, and $fbsecret, respectively.) I keep these in a separate file, which I name config.inc.php. It looks like this:
You'll fill out your app's data, of course, which you can find in it's Developer profile. Include the data in the main program with a simple require statement:
Now we start checking for weird cases. For instance, some joker might examine the code and figure out where you keep your server. And then he'll visit you directly. Hence, this bit of code:
If the user has created a bookmark for your app, he might visit while he's not logged in to Facebook. That'll never do! We'd better check for that, which Facebook indicates by setting 'fb_sig_logged_out_facebook' in the GET or POST variables:
Having covered the instant-failure cases, we can move on to the complicated cases. For these, we'll have to create a Facebook object and try to retrieve the user's ID. The user might be just visiting the canvas page, in which case we'd like to give him a preview of the app, with all the functionality we can provide. Alternatively, he might be a "logged in" user: a user who has given us additional permissions, and who can therefore access all our app's features. You call get_canvas_user() to get the ID for the casual user, and get_logged_in_user() for the full user:
Unfortunately, this doesn't cover quite all the possibilities. If the user came from a non-Facebook page, the user ID won't be set at all, and we'll need him to click a link to get within the Facebook structure. If the user's privacy settings are restrictively high, the ID won't be set either, and he'll need to allow us to access his data. But how can we tell the difference? Easy: if he came from a Facebook page, '_fb_fromhash' is set.
Once we've gotten pas this point, we're guaranteed to have a valid user ID in the $user_id variable. We can carry on with the actual application. We might want to save the user ID for later.
Put it all together, and you get a nice skeleton for an FBML Facebook app. I'm using this skeleton with my first Facebook app, which I hope to release soon.