In this post I will talk about how to create a Facebook Connect site using the CodeIgniter framework.
The first key step to this is to extend the base controller and create a Facebook Controller that can handle user authentication and pass other needed variables:
class Facebook_Controller extends Controller {
var $facebook;
var $fb_uid;
var $fb_user_details;
var $user;
var $permissions_to_request;
var $logged_in;
public $data;
function Facebook_Controller() {
parent::Controller();
$this->output->set_header("Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
$this->output->set_header("Pragma: no-cache");
// Created some Facebook helper functions to make things easier and pull API Key, Secret Key, Base URLs, etc from the Facebook config file.
$this->__fbApiKey = get_facebook_api_key();
$this->__fbSecret = get_facebook_secret_key();
// Prevent the 'Undefined index: facebook_config' notice from being thrown.
$GLOBALS['facebook_config']['debug'] = NULL;
// Create a Facebook client API object.
$this->facebook = new Facebook($this->__fbApiKey, $this->__fbSecret);
$this->fb_uid = $this->facebook->get_loggedin_user();
//Check to see if the user is logged in with facebook
if($this->fb_uid)
{
$fb_uid = $this->fb_uid;
//If this is the first login with the site
if(!$this->_get_user_session_object($fb_uid))
{
//Check to see if user is in the db
$this->load->model('User_model');
$this->user = $this->User_model->get_user_by_fb_uid($fb_uid);
$this->fb_user_details = $this->Facebook_model->get_user_details($fb_uid);
//If its not in the db, do an insert
if(!$this->user)
{
$user_data = array('fb_uid' => $fb_uid, 'created_at' => date('Y-m-d H:i:s'));
$user_id = $this->User_model->insert_user($user_data);
//Give them a default username
$user_data = array('username' => 'user'.$user_id);
$this->User_model->update_user($user_id, $user_data);
$this->user = $this->User_model->get_user_by_user_id($user_id);
}
$this->_set_user_session_object($fb_uid, $this->user);
$this->_set_user_details_session_object($fb_uid, $this->fb_user_details);
//Check to see if user has all the required permissions
$has_publish_stream_permission = $this->facebook->api_client->call_method('Users.hasAppPermission',array('ext_perm'=>'publish_stream', 'uid'=>$fb_uid));
$has_email_permission = $this->facebook->api_client->call_method('Users.hasAppPermission',array('ext_perm'=>'email', 'uid'=>$fb_uid));
//Request the missing permissions
$permissions_to_request = $has_publish_stream_permission == 0 ? "publish_stream" : null;
if($permissions_to_request)
$permissions_to_request .= ",";
$permissions_to_request .= $has_email_permission == 0 ? "email" : null;
// I wanted to use this approach but it left a trailing comma in the end so it didn't work out. I'm sure there is a way around it.
//$arry_permissions_to_request = array($has_publish_stream_permission == 0 ? "publish_stream" : null, $has_email_permission == 0 ? ",email" : null);
//$permissions_to_request = implode(",", $arry_permissions_to_request);
$this->permissions_to_request = $permissions_to_request;
}
else
{
//Load the user object back from the session
$this->user = $this->_get_user_session_object($this->fb_uid);
$this->fb_user_details = $this->_get_user_details_session_object($this->fb_uid);
}
}
//Set master page data variables
$this->data['user'] = $this->user;
$this->data['fb_user_details'] = $this->fb_user_details;
$this->logged_in = ($this->user && $this->fb_uid)? true : false;
$this->data['logged_in'] = $this->logged_in;
$this->data['request_permissions'] = $this->permissions_to_request ? true : false;
$this->data['permissions_to_request'] = $this->permissions_to_request;
$this->data['fb_login_prompt'] = false;
$this->data['current_controller'] = get_class($this);
}
function _get_user_session_object($fb_uid)
{
return $this->session->userdata($fb_uid.'_user_object');
}
function _get_user_details_session_object($fb_uid)
{
return $this->session->userdata($fb_uid.'_user_details_object');
}
function _set_user_session_object($fb_uid, $user)
{
$this->session->set_userdata($fb_uid.'_user_object', $user);
}
function _set_user_details_session_object($fb_uid, $fb_user_details)
{
$this->session->set_userdata($fb_uid.'_user_details_object', $fb_user_details);
}
}
Once we have that setup, we can go ahead and create a master page which will load the header, footer, navigation and all the other site-wide global elements. Part of which, the header, could look something like this, it would show the user’s profile pic & name when logged in and show a Facebook Connect button when logged out:
<div id="header">
<?php if (!$logged_in) { ?>
<div style="margin-top:18px">
<a href="#" id="fbconnect_login_button" class="fbconnect_login_button" onclick="FB.Connect.requireSession(); return false;" >
<img id="fb_login_image" src="http://static.ak.fbcdn.net/images/fbconnect/login-buttons/connect_light_medium_long.gif" style="border:0;" alt="Connect"/>
</a>
</div>
<?php } else { ?>
<div class="floatR">
<fb:profile-pic uid="<?=$user['fb_uid']?>" size="square" facebook-logo="true"></fb:profile-pic>
</div>
<div class="floatR" style="margin-top:13px">
Welcome, <?=$fb_user_details[0]['name']?>
<br />
<a href="#" onclick="FB.Connect.logout(function() { facebook_onlogout(); }); facebook_onlogout()">Logout of Facebook</a>
</div>
<br class="clearFloat" />
<?php } ?>
</div>
Content area would just be one variable which will load the content from the page controller as we will see further on:
<div id="mainContent"> <?=$content?> </div>
And finally, the most important part, the footer which would load & initialize the Facebook library, take care of prompting for the right permissions, and require the user to login on certain pages based on the controller:
<div id="footer">
<script type="text/javascript">
function setFocus() { window.document.<?=$current_controller?>.focus(); }
</script>
<script src="<?=get_static_facebook_root();?>/js/api_lib/v0.4/FeatureLoader.js.php/en_US" type="text/javascript"></script>
<script type="text/javascript">
FB.init("<?=get_facebook_api_key();?>", "<?=base_url();?>xd_receiver.htm", {"reloadIfSessionStateChanged":true});
</script>
<script src="<?=base_url();?>shared/js/fbconnect.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = function() {
facebook_onload(<?=$logged_in?>);
<?php if ($request_permissions) { ?>facebook_prompt_permission("<?=$permissions_to_request?>");<?php } ?>
};
</script>
<?php if ($fb_login_prompt && !$logged_in) { ?>
<script type="text/javascript">
FB.ensureInit(function() {
FB.Connect.requireSession(null, function(){ location.href = "<?=base_url();?>home"; });
});
</script>
<?php } ?>
</div>
As you can see, I’ve used some JavaScript in fbconnect.js to help us invoke the permissions and/or dialog box as needed:
/*
* The facebook_onload statement is printed out in the PHP. If the user's logged in
* status has changed since the last page load, then refresh the page to pick up
* the change.
*
* This helps enforce the concept of "single sign on", so that if a user is signed into
* Facebook when they visit your site, they will be automatically logged in -
* without any need to click the login button.
*
* @param already_logged_into_facebook reports whether the server thinks the user
* is logged in, based on their cookies
*
*/
function facebook_onload(already_logged_into_facebook) {
// user state is either: has a session, or does not.
// if the state has changed, detect that and reload.
FB.ensureInit(function() {
FB.Facebook.get_sessionState().waitUntilReady(function(session) {
var is_now_logged_into_facebook = session ? true : false;
// if the new state is the same as the old (i.e., nothing changed)
// then do nothing
if (is_now_logged_into_facebook == already_logged_into_facebook) {
return;
}
// otherwise, refresh to pick up the state change
refresh_page();
});
});
}
function facebook_onlogin_ready() {
refresh_page();
}
function facebook_onlogout() {
$.post("./Logout", null, null);
}
function refresh_page() {
location.reload(true);
}
function facebook_prompt_permission(permission) {
FB.ensureInit(function() {
FB.Connect.showPermissionDialog(permission);
});
}
Now that we have the master page setup, we can inject our content into the master page from any page controller:
class Test extends Facebook_Controller {
function Test()
{
parent::Facebook_Controller();
}
function Index()
{
$this->data['fb_login_prompt'] = true;
$this->data['content'] = $this->load->view('test', $this->data, true);
$this->load->view('layouts/master' ,$this->data);
}
So, thats it! Now you should have a fully functional Facebook connect site in CodeIgniter!
Inspired by:
http://junal.wordpress.com/2008/01/20/a-sample-facebook-application-with-codeigniter/
http://www.simpleprojectz.com/2008/10/facebook-codeigniter/
http://codeigniter.com/forums/viewthread/120393/
Tags: codeigniter, facebook, php






