Tutorial: Integrate Facebook Connect to your website using PHP SDK v.3.x.x which uses Graph API

Now-a-days it is common for websites to have Facebook Connect integrated to it. Facebook Connect is the iteration of Facebook Platform that allows users to ‘connect’ their Facebook identity, friends and privacy to any site. It enables a website to implement features of Facebook platform on it. Facebook Connect has been around since May 2008. Since then, Facebook has released various Software development kits (SDK) namely JavaScript SDK, PHP SDK, iOS SDK (iPhone & iPad) and Android SDK for easy implementation of their API. In this tutorial we will be concentrating on PHP SDK. As of today, the latest version of PHP SDK is 3.1.1 which was released on August 10, 2011. PHP SDK v3.x.x is a major update from v2.2.x, as the new SDK uses OAuth authentication flows instead of Facebook’s legacy authentication flow. The new SDK has two classes. The first (BaseFacebook) maintains the core of the upgrade, and the second one (Facebook) is a subclass that uses PHP sessions to store the user id and access token.

Facebook has made it clear that, all website and canvas apps must exclusively support OAuth 2.0 (draft 20) by October 1, 2011. The OAuth 2.0 authorization protocol enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf. Facebook insists all canvas apps to use the ’signed_request’ parameter. Because of this, it is mandatory for all developers to migrate to new version (v3.x.x) as older versions will stop working from October 1, 2011.

Registering your application

Steps 1 to 3 will explain the procedure of registering the application at Facebook. You need to register at Facebook and obtain App ID and App Secret, for the application to work.

Step 1:

The primary step is to visit http://developers.facebook.com/apps.

If you are visiting this URL for the first time, you will have a window similar to the one shown below in which Facebook developer app will request your permission to access your basic information.

Click the ‘Allow’ button.

Step 2:

Now you be on a page that shows you your recently viewed app. Don’t worry if it doesn’t show any app. It just means that you haven’t created any app yet.

Now, click ‘Create New App’ button.

Create New App

Create New App

In the window that pops up, enter the name of your application. Mark the check box ‘I agree to Facebook Terms’ and click ‘Continue’ button.

Now you may be asked to solve a captcha which verifies that you are human.

Step 3:

You will be taken to the application basic settings page.

On the top portion of the page you will have your ‘App ID’ and ‘App Secret’. Please note them as we will need them in Step 5.

Enter your domain name as ‘App Domain’. Please note that a ‘your-domain.com’ will include ‘*.your-domain.com’ also. That is, you can use the app on any of your sub-domains. You can even enter ‘localhost’ if you are testing your application on your local machine.

In the ‘Website’ section, you need to enter ‘Site URL’. ‘Site URL’ will be entry page for your application. As we are making a webpage that has f-connect enabled, we need to give the address of the webpage that we are about to make. In my case, it is http://25labs.com/demo/fb/index.php. Site URL will be the redirect URL for your application. Because of security reasons, Facebook will redirect users to this URL only. We will be creating webpage in the later sections. If you are not sure about what your URL will be, just leave the field blank as you can fill it any time later.

 Now click ‘Save Changes’.

The registration of your application is now complete. Now we will move on to build our application.

Downloading PHP SDK

Facebook releases its PHP Software Development kit so that developers can easily integrate their Graph API to the applications.

Step 4:

Download the latest version of PHP SDK from GitHub.

Extract the compressed file and you will find folders and files similar to the one shown below.

PHP SDK folder structure

PHP SDK folder structure

Upload the above shown folders to the webhost where you wish to have your webpage. In my case it is ‘25labs.com/demo/fb/’. For the application to run, only the folder ‘src’ is required. All other files and folders are examples, tests, logs etc and so they can be optionally discarded.

Creating the access file (fbaccess.php)

Create a file ’fbaccess.php’.

In steps 5 to 10, I will explain the file part by part.

Step 5:

The first part is Application Configurations. In this part we have 3 variables – $app_id, $app_secret, and $base_url.

Replace ‘Your App ID/API Key goes here’ and ‘Your App secret goes here’ with the ‘App ID’ and ‘App Secret’ that you created in Step 3, respectively.

Replace ‘Your Site URL goes here’ with the ‘Site URL’ that you entered in Step 3. If you are still not sure of your site URL, leave it as such. You can come back and edit it after step 11.

$app_id		= "Your App ID/API Key goes here";
$app_secret	= "Your App secret goes here";
$site_url	= "Your Site URL goes here";

Step 6:

Now, include ‘facebook.php’ which can be found in the ‘src’ folder of PHP SD that you downloaded.

Then you need to create an application instance using the constructor of class ‘Facebook’. The App ID and App Secret need to be passed as arguments for the constructor. In earlier versions of PHP SDK (v2.x.x), the argument array had an optional key ‘session’. But in v3.x.x, ‘session’ key is not used at all.

Then we call the function getUser() which will return the user ID. We will be using a variable ‘$user’ to store the User ID of Facebook user. We may or may not have this data based on whether the user is logged in. If we have a $user id here, it means we know the user is logged into Facebook, but we don’t know if the access token is valid. An access token is invalid if the user logged out of Facebook.

include_once "src/facebook.php";
 
$facebook = new Facebook(array(
	'appId'		=> $app_id,
	'secret'	=> $app_secret,
	));
 
$user = $facebook->getUser();

Step 7:

If we get a User ID in the previous step, it means that we have a logged in user. Now we need to check whether the logged in user is authenticated to run the application.

For this, we call the ‘api’ function with value ‘/me’. If the user is authenticated, api(‘/me’) will return the profile information of the user. If the user is not authenticated, the function will produce an exception. We catch this exception and then make the ‘$user’ variable NULL so that the user can be asked to authenticate.

if($user){
//==================== Single query method ======================================
	try{
		// Proceed knowing you have a logged in user who's authenticated.
		$user_profile = $facebook->api('/me');
	}catch(FacebookApiException $e){
		error_log($e);
		$user = NULL;
	}
//==================== Single query method ends =================================
}

This try catch-block is also an example for single query method. Different arguments can be used for function ‘api’ to return various results for authenticated users in single query method. Full set of arguments can be found at https://developers.facebook.com/docs/reference/api/

Step 8:

After Step 7, variable ‘$user’ will hold Facebook User ID if we have a logged in authenticated user, and NULL otherwise.

If it holds a User ID, it means that the user is logged into the application. So we need a logout URL. If the variable is NULL, it means that user is not logged in and we need a login URL.

We use functions getLoginUrl() and getLogoutUrl() to get the login and logout URL respectively. The argument for getLoginUrl() is an array with optional keys ‘scope’ and ‘redirect_uri’.

$loginUrl = $facebook->getLoginUrl(array(
		'scope'		=> 'Your list of Permissions', // Permissions to request from the user
		'redirect_uri'	=> 'Your Site URL', // URL to redirect the user to once the login/authorization process is complete.
		));

The ‘scope’ field will contain a comma separated list of permissions to request from the user. You must ask for all the permissions that you need for the app to work. For example, if you need email, birthday and location of the user, then you must specify ‘email, user_birthday,user_location’ in the scope field. In my case, I need permission to retrieve news feed, publish stream, birthday, location, work history, hometown and user photos. Thus my ‘scope’ parameter is ‘read_stream, publish_stream, user_birthday, user_location, user_work_history, user_hometown, user_photos’. You can read about the full list of permissions at https://developers.facebook.com/docs/reference/api/permissions/.

‘redirect_uri’ field will contain the URL to redirect the user to, once the login/authorization process is complete. The user will be redirected to the URL on both login success and failure. If this property is not specified, the user will be redirected to the current URL (i.e. the URL of the page where this method was called, typically the current URL in the user’s browser).

The argument for getLogoutUrl() is an optional array with key ‘next’ which contain Next URL to which to redirect the user after logging out.

$logoutUrl = $facebook->getLogoutUrl(array(
		'next'	=> 'Your Redirect URL after logout', // URL to which to redirect the user after logging out
		));

Please note that it should be an absolute URL. If this property is not specified, the user will be redirected to the current URL.

For my application webpage, the complete code for login and logout URL is shown below.

if($user){
	// Get logout URL
	$logoutUrl = $facebook->getLogoutUrl();
}else{
	// Get login URL
	$loginUrl = $facebook->getLoginUrl(array(
		'scope'	=> 'read_stream, publish_stream, user_birthday, user_location, user_work_history, user_hometown, user_photos',
		));
}

Step 9:

Now we need to retrieve the information that we need if we have a logged in authenticated user. For that we can use the single query method mentioned in Step 7. The below code retrieve user info, news feed, friends list and photos of the logged in user. You can also specify an optional limit for many queries.

try{
	$user_info	= $facebook->api('/' . $user);
	$feed		= $facebook->api('/' . $user . '/home?limit=50');
	$friends_list	= $facebook->api('/' . $user . '/friends');
	$photos		= $facebook->api('/' . $user . '/photos?limit=6');
}catch(FacebookApiException $e){
	error_log($e);
}

You can notice that it takes 4 requests to the graph API. It can slow down the page significantly and also increase the load. So it will be better if we can combine all these requests. For that we use Batch requests. All the queries can be saved to an array. We encode the array as JSON and POST this JSON to batch endpoint on the graph. It will return values that are indexed in order of the original array. The content will be in ['body'] as a JSON and we need to decode the JSON to get the results as a PHP array. Batch query replacement for single query method is shown below.

//========= Batch requests over the Facebook Graph API using the PHP-SDK ========
	// Save your method calls into an array
	$queries = array(
		array('method' => 'GET', 'relative_url' => '/'.$user),
		array('method' => 'GET', 'relative_url' => '/'.$user.'/home?limit=50'),
		array('method' => 'GET', 'relative_url' => '/'.$user.'/friends'),
		array('method' => 'GET', 'relative_url' => '/'.$user.'/photos?limit=6'),
		);
 
	// POST your queries to the batch endpoint on the graph.
	try{
		$batchResponse = $facebook->api('?batch='.json_encode($queries), 'POST');
	}catch(Exception $o){
		error_log($o);
	}
 
	//Return values are indexed in order of the original array, content is in ['body'] as a JSON
	//string. Decode for use as a PHP array.
	$user_info		= json_decode($batchResponse[0]['body'], TRUE);
	$feed			= json_decode($batchResponse[1]['body'], TRUE);
	$friends_list		= json_decode($batchResponse[2]['body'], TRUE);
	$photos			= json_decode($batchResponse[3]['body'], TRUE);
//========= Batch requests over the Facebook Graph API using the PHP-SDK ends =====

Step 10:

You can update user’s status by using the method mentioned below. We POST the status to ‘/UserID/feed’. (‘UserID’ to be replaced with the required user’s ID). The status to be posted is an array with optional fields – message, link, picture, name, caption, and description.

try {
	$publishStream = $facebook->api("/$user/feed", 'post', array(
		'message'		=> 'Check out 25 labs',
		'link'			=> 'http://25labs.com',
		'picture'		=> 'http://25labs.com/images/25-labs-160-160.jpg',
		'name'			=> '25 labs',
		'caption'		=> '25labs.com',
		'description'		=> 'A Technology Laboratory. Highly Recomented technology blog.',
		));
}catch(FacebookApiException $e){
	error_log($e);
}

If you just want a status message, then just omit all other fields.

try{
	$statusUpdate = $facebook->api("/$user/feed", 'post', array('message'=> 'Your Status goes here'));
}catch(FacebookApiException $e){
	error_log($e);
}

Complete fbaccess.php for my webpage

(Codes in Step 5 to 10 combined)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<?php
//Application Configurations
$app_id		= "Your App ID/API Key goes here";
$app_secret	= "Your App secret goes here";
$site_url	= "Your Site URL goes here";
 
try{
	include_once "src/facebook.php";
}catch(Exception $e){
	error_log($e);
}
// Create our application instance
$facebook = new Facebook(array(
	'appId'		=> $app_id,
	'secret'	=> $app_secret,
	));
 
// Get User ID
$user = $facebook->getUser();
// We may or may not have this data based
// on whether the user is logged in.
// If we have a $user id here, it means we know
// the user is logged into
// Facebook, but we don’t know if the access token is valid. An access
// token is invalid if the user logged out of Facebook.
 
if($user){
//==================== Single query method ======================================
	try{
		// Proceed knowing you have a logged in user who's authenticated.
		$user_profile = $facebook->api('/me');
	}catch(FacebookApiException $e){
		error_log($e);
		$user = NULL;
	}
//==================== Single query method ends =================================
}
 
if($user){
	// Get logout URL
	$logoutUrl = $facebook->getLogoutUrl();
}else{
	// Get login URL
	$loginUrl = $facebook->getLoginUrl(array(
		'scope'		=> 'read_stream, publish_stream, user_birthday, user_location, user_work_history, user_hometown, user_photos',
		'redirect_uri'	=> $site_url,
		));
}
 
if($user){
	// Proceed knowing you have a logged in user who has a valid session.
 
//========= Batch requests over the Facebook Graph API using the PHP-SDK ========
	// Save your method calls into an array
	$queries = array(
		array('method' => 'GET', 'relative_url' => '/'.$user),
		array('method' => 'GET', 'relative_url' => '/'.$user.'/home?limit=50'),
		array('method' => 'GET', 'relative_url' => '/'.$user.'/friends'),
		array('method' => 'GET', 'relative_url' => '/'.$user.'/photos?limit=6'),
		);
 
	// POST your queries to the batch endpoint on the graph.
	try{
		$batchResponse = $facebook->api('?batch='.json_encode($queries), 'POST');
	}catch(Exception $o){
		error_log($o);
	}
 
	//Return values are indexed in order of the original array, content is in ['body'] as a JSON
	//string. Decode for use as a PHP array.
	$user_info		= json_decode($batchResponse[0]['body'], TRUE);
	$feed			= json_decode($batchResponse[1]['body'], TRUE);
	$friends_list		= json_decode($batchResponse[2]['body'], TRUE);
	$photos			= json_decode($batchResponse[3]['body'], TRUE);
//========= Batch requests over the Facebook Graph API using the PHP-SDK ends =====
 
	// Update user's status using graph api
	if(isset($_POST['publish'])){
		try{
			$publishStream = $facebook->api("/$user/feed", 'post', array(
				'message'		=> 'Check out 25 labs',
				'link'			=> 'http://25labs.com',
				'picture'		=> 'http://25labs.com/images/25-labs-160-160.jpg',
				'name'			=> '25 labs',
				'caption'		=> '25labs.com',
				'description'		=> 'A Technology Laboratory. Highly Recomented technology blog.',
				));
		}catch(FacebookApiException $e){
			error_log($e);
		}
	}
 
	// Update user's status using graph api
	if(isset($_POST['status'])){
		try{
			$statusUpdate = $facebook->api("/$user/feed", 'post', array('message'=> $_POST['status']));
		}catch(FacebookApiException $e){
			error_log($e);
		}
	}
}
?>

Creating the main webpage

Now we will be creating the main page of the website. It will be the one that is visible to the users.

Step 11:

Create a PHP file (In my case it is index.php).

Include ‘fbaccess.php’ into it.

‘fbaccess.php’ will give you a NULL ‘$user’ variable and ‘$loginUrl’ for a user who is not logged in and authenticated. So, if ‘$user’ is not set, make a login button or link and make ‘$loginUrl’ its destination. User can click this button and login to your webpage.

If ‘$user’ is set (logged in authenticated user), ‘fbaccess.php’ will give you 5 variables – $logoutUrl, $user_info, $feed, $friends_list, and $photos. Except $logoutUrl, all others are PHP arrays.

If you print the array ‘$user_info’ it will look something similar to this.

Array
(
    [id] => 100002936955841
    [name] => Unni Krishnan
    [first_name] => Unni
    [last_name] => Krishnan
    [link] => http://www.facebook.com/profile.php?id=100002936955841
    [birthday] => 01/02/1988
    [hometown] => Array
        (
            [id] => 110383752315912
            [name] => Trivandrum, India
        )
    [gender] => male
    [timezone] => 5.5
    [locale] => en_US
    [updated_time] => 2011-09-18T14:16:25+0000
)

You can use these variables which has all the information you need, to make your webpage. Please note that user’s first name, last name and profile picture are publicly available and you don’t need PHP SDK or an access token to retrieve them.

The below mentioned link can be used to get the profile picture of a user.

https://graph.facebook.com/zuck /picture?type=large

In the above example ‘zuck’ is Mark Zuckerberg’s username.

You can specify the picture size you want with the ‘type’ argument, which should be one of square (50×50), small (50 pixels wide, variable height), normal (100 pixels wide, variable height), and large (about 200 pixels wide, variable height).

When complete, upload the page to the host where you need your f-connect enabled website need to be. Please not the URL of the page as it will act as your site URL. If you had skipped to enter the Site URL in Step 3 and 5, please go back and enter them.

You can download the complete source of my demo webpage from here.

User Authentication

When a user login at your webpage for the first time, he will have to grant permission for accessing his details. It will look similar to this.

Once the user clicks ‘Allow’ he will be redirected to your webpage as an authenticated user.

Issues you may face

Any errors that you get will be logged in your hosts error log. Please check log to get information on errors, if any.

Session Error:

You may get a similar warning in your error log.

Warning: session_start() [<a href='function.session-start'>function.session-start</a>]:
Cannot send session cookie - headers already sent

In this case getUser() function will return 0 for all users even if they are logged in. This happens because session doesn’t get saved in your host.

Solution:

Make sure the session.save_path in php.ini is set and point to a valid path. In many hosts the line session.save_path would be commented out. In that case please uncomment the line.

Hope everything worked well. Comment below if you face any problems or find any improvements to the script.