I’ve been testing the facebook php-sdk for a while and I had some problems with it. mostly, I had some cookies issues, not being set correctly, or simply not working. I had solved these problems and I’ll show you how to do it.
my system is a fedora 14 64 bits and I’m behind an apache 2.2.17 with php 5.3.6. also, I’m using the facebook php-sdk 2.1.2, available at github. the facebook-php-sdk requires the extension php-curl to be installed.
creating an facebook app
first of all, you’ll need to create an application inside facebook. it’s very easy, follow these steps:
1. go to http://developers.facebook.com/
2. click on “My Apps”, in the near top right corner
3. click on “Set Up New App”
4. set a name of the app, read the docs, select “I agree” and click on “Create App”
5. you’ll need to confirm a captcha and we’re done.
if everything runs fine, you’re now on your new application edit page. if you’re not, I’ll show you how to find it:
1. go to http://www.facebook.com/developers/
2. click on “See My Apps” in the right column
3. select you application in the left column and click on “edit configurations”
currently, we’ll only to need to configure a little. select “Web Site”, in the left column and:
1. copy the “Application ID” and the “Application Secret”. You’ll need them to access facebook.
2. in “Site URL”, I put “http://localhost/fb/”, since I’m just doing tests.
3. in “Site Domain”, I put “localhost”, since I’m just doing tests.
you’ll need to update these info if you’re in a live website. and, of course, there are a lot of other relevant info you’ll may want to update as well.
loging in with facebook
what I’m going to do here is just an very very basic example. if you want to consume relevant user info or do other advanced tasks, you’ll have to refer to the official docs. this is just a pre-step so you can run the sdk correctly.
we’re going localhost. its fairly easy:
1. create a folder in your apache document folder folder called ‘fb’ (depending on your system, it may be called ‘htdocs’, ‘/var/www/’, ‘/var/www/html/’ or something like that)
2. open the facebook-php-sdk-v2.1.2-0-*.zip and extract the facebook-php-sdk-*/src/facebook.php to the folder ‘fb’;
3. inside ‘fb’, create a php file called ‘index.php’ with the following contents:
<?php
require 'facebook.php';
$facebook = new Facebook(array(
'appId' => 'APP_ID',
'secret' => 'APP_SECRET',
'cookie' => true,
));
//2. retrieving session
$session = $facebook->getSession();
//3. requesting 'me' to API
$me = null;
if ($session) {
try {
$uid = $facebook->getUser();
$me = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
}
}
//4. login or logout
if ($me) {
$logoutUrl = $facebook->getLogoutUrl();
} else {
$loginUrl = $facebook->getLoginUrl();
}
?>
<!doctype html>
<html xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<title>php-sdk</title>
</head>
<body>
<?php if ($me): ?>
<?php echo "Welcome, ".$me['first_name']. ".<br />"; ?>
<a href="<?php echo $logoutUrl; ?>">
<img src="http://static.ak.fbcdn.net/rsrc.php/z2Y31/hash/cxrz4k7j.gif">
</a>
<?php else: ?>
<a href="<?php echo $loginUrl; ?>">
<img src="http://static.ak.fbcdn.net/rsrc.php/zB6N8/hash/4li2k73z.gif">
</a>
<?php endif ?>
</body>
</html>
this file is freely based on the example provided in the facebook-php-sdk-v2.1.2-0-*.zip package. you’ll need to replace the APP_ID and the APP_SECRET with the contents you’ve copied before.
in the commented parts of the code, in 1, you’re creating an Facebook object, which will be your bridge to the Facebook webservices; also, you’re specifying that you want to use cookies as session storage method. in 2, you’re retrieving a session; you *need* to do this, so the Facebook object can fetch the session data from the state before. if you do not do this, none of the following commands assuming the existence of a session will work. in 3, you’re doing a simple request to the API, asking for your profile public data. and, finally, in 4, if $me is empty, it means that you’re not logged in, and the variables are set properly.
now, acess http://localhost/fb/index.php and let’s see the magic. the first time ever when you try to login in the webpage, you’ll be redirected to a facebook page where you’ll have to give permission for the app to access your data. this just happens once. and when you click logout, you’re logging out of Facebook.
ok, now lets see some fun stuff. log in and then acess http://localhost/fb/index.php , without all that strange parameters you see on the url when you’re logged in. a strange thing happens: the script does not detect you’re already logged in. you can verify this by going to the facebook home and see you’re actually logged in!
according to this comment, this happens because php does not set cookies correctly for the localhost domain. for this to work, you’ll need to change a little bit the facebook.php file. go to the line 661-663 and replace them with:
if ($domain) {
$domain = '.' . $domain;
if ($domain == '.localhost') $domain = false;
}
and done! now, you can login, access http://localhost/fb/index.php, and the session will be correctly set!
further and very important comments
there an very important comment I have to make: when you logout, the session is still set. when you login, you define a cookie that has an access token, so your application can access your data. to the Facebook object, this access token is available even when you logout (which, in my opinion, should not occur). your script detects that the access token is not valid anymore when it tries to fetch the ‘/me’ data from the API and an exception occurs. if the access token is not valid anymore and you want to make an API request, you receive something like that:
“Fatal error: Uncaught OAuthException: Error validating access token: The session is invalid because the user logged out or because auth.expireSession was invoked.(…)”
to prevent this from happening, you have two choices:
1. specify a return_url for the logout: this is a parameter you specify when invoking the getLogoutUrl() method. this is how you do it, for instance:
$logoutUrl = $facebook->getLogoutUrl(array( 'next'=>'http://localhost/fb/logout.php' ));
and, in this address, you can manually empty the cookie. see the full code for ‘logout.php’:
<?php
require 'facebook.php';
$facebook = new Facebook(array(
'appId' =--> 'APP_ID',
'secret' => 'APP_SECRET',
'cookie' => true,
));
//ovewrites the cookie
$facebook->setSession(null);
//redirects to index
header('Location: http://localhost/fb/index.php');
?>
2. empty the cookies everytime a request fails: now, when the user access any page that asks for getSession(), it will be empty, and you won’t need to fetch ‘/me’ from the API to know if the access token is still valid, altough it is a good pratice always surround it with try-catch statements. now, we can make a modification to index.php, so itself can empty the cookie when the access token is not valid anymore. let the try-catch block look like the following:
try {
$uid = $facebook->getUser();
$me = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$facebook->setSession(null);
}
the benefit of this is, when your user has logged out and it was not through your application, you’ll can empty the cookie and do not make further requests to API.
3. specify a return_url for the login: this will clean the url. when you’re loging in, the facebook will pass a lot of parameters to you scripts that will be parsed by the Facebook object. you can prevent them from showing in your url specifying a returl_url for the login.
$loginUrl = $facebook->getLoginUrl(array(
'next'=>'http://localhost/fb/login.php'
));
and the code for login.php:
<?php
require 'facebook.php';
$facebook = new Facebook(array(
'appId' =--> 'APP_ID',
'secret' => 'APP_SECRET',
'cookie' => true,
));
$session = $facebook->getSession();
//redirects to index
header('Location: http://localhost/fb/index.php');
?>
4. you can use ‘offline_access’: this provides you a long term access token, so you can access user data and post updates in his profile even when he is not using your app. here you can see an example of how to use it (I didn’t tested it).
of course, there are a LOT of other things you can explore with facebook-php-sdk, the Graph API and a plethora of other webservices that Facebook has to offer. this is a very brief introduction, so you can have a little example running locally and can make your tests. you can check this page for more examples with the Graph API (I didn’t tested it).
you can download the code here:
http://cacovsky.googlecode.com/files/facebook-login-example.zip
(don’t forget to replace APP_ID and APP_SECRET with the appropriate values in config.php!)
useful links:
the facebook php sdk
facebook developers
facebook developer docs
issue with facebook php sdk and localhost cookies
error validating access token
setting return url
authentication permissions
using offline access token
examples with the facebook Graph API