Integrating Facebook Connect

by fsiebler
In this Tutorial I will show you how easily you can integrate the new Facebook Connect Open Graph API into your CakePHP Application.
In this Tutorial we are using the CakePHP Auth Component. Make sure that this is working before you starting this tutorial.

First you have to create a (New) Application on the developers.facebook.com Homepage to get you API, APP, and Secret Vars for the API. These are required for Facebook to correctly integrate with external applications.

You need to add a few new properties to you app_controller.php class. We need this later to interact with the Facebook API

Controller Class:

<?php 
class AppController
...
        var 
$FACEBOOK_APP_ID '...';
        var 
$FACEBOOK_API_ID '...';
        var 
$FACEBOOK_SECRET '...';
        var 
$FACEBOOK_COOKIE '';

?>

In the Next step we will create two new function in the app_controller.php class.
The function get_facebook_cookie() is to get the Cookie which is set later by the Connect Script from the Client.

The __checkFBStatus() Function is to Check, Login and Create the User Account in your System.

Controller Class:

<?php 
class AppController
        
...
        function 
get_facebook_cookie($app_id$application_secret) {
          
$args = array();
          if (isset(
$this->Cookie->read('fbs_' $app_id))) {
                
parse_str(trim($this->Cookie->read('fbs_' $app_id), '\\"'), $args);
                
ksort($args);
                
$payload '';
                  foreach (
$args as $key => $value) {
                    if (
$key != 'sig') {
                      
$payload .= $key '=' $value;
                    }
                  }
                if (
md5($payload $application_secret) != $args['sig']) {
                return 
null;
                }
          }
          return 
$args;
        }


        private function 
__checkFBStatus(){
            
$this->loadModel('User');
            
//check to see if a user is not logged in, but a facebook user_id is set
            
if(!$this->Auth->User() && $this->FACEBOOK_COOKIE) {
                        
//see if this facebook id is in the User database; if not, create the user 
                        
$user_record $this->User->find('first', array(
                           
'conditions' => array('username' => $this->FACEBOOK_COOKIE['uid']),
                           
'fields' => array('User.username''User.passwd'),
                           
'contain' => array()
                        ));


                
//create new user
                
if(empty($user_record)) {
                    
                    
// I need this make no changes to the model
                    
$save_options = array( 'validate' => false);
                    
// get the User Data from Facebook...
                    
$a_user json_decode(file_get_contents('https://graph.facebook.com/me?access_token='.$this->FACEBOOK_COOKIE['access_token']));

                    
$user_record['User']['token'] = sha1($this->FACEBOOK_COOKIE['uid'].'evmgr');
                    
$user_record['User']['username'] = $this->FACEBOOK_COOKIE['uid'];
                    
$user_record['User']['fbid'] = $this->FACEBOOK_COOKIE['uid'];
                    
$user_record['User']['group_id'] = 2;
                    
$user_record['User']['active'] = 1;
                    
$user_record['User']['name'] = $a_user->first_name;
                    
$user_record['User']['lastname'] = $a_user->last_name;
                    
$user_record['User']['website'] = $a_user->website;
                    
$user_record['User']['birthday'] = date('Y-m-d'strtotime($a_user->birthday));
                    
$user_record['User']['facebook_link'] = $a_user->link;
                    
$user_record['User']['email'] = $this->FACEBOOK_COOKIE['uid'].'@facebookuser.de';
                    
$user_record['User']['new_passwd_hash'] = $this->Auth->password($this->__randomString());
                    
$user_record['User']['new_passwd'] = $user_record['User']['new_passwd_hash'];
                    
$user_record['User']['confirm_passwd'] =  $user_record['User']['new_passwd_hash'];
                    
$user_record['User']['passwd'] = $user_record['User']['new_passwd_hash'];

                    
// Create the User
                    
if($this->User->save($user_record$save_options)){
                        
// all ok. do nothing...
                    
}else{
                        
// interact to flush a error msg.
                    
}
                }

                
//change the Auth fields if you need this
                
$this->Auth->fields = array('username' => 'username''password' => 'passwd');

                
//log in the user with facebook credentials
                
$this->Auth->login($user_record);

            }
        }
?>

Then we need to call the get_facebook_cookie() function in the constructor to get the Cookie data.
To create or Login the User we need to call the __checkFBStatus() in the beforeFilter.

Controller Class:

<?php 
class AppController
   
...
   function 
__construct() {
      
parent::__construct();
      
// get the Facebook Cookie
      
$this->FACEBOOK_COOKIE $this->get_facebook_cookie($this->FACEBOOK_APP_ID$this->FACEBOOK_SECRET);

   }

   function 
beforeFilter() {
        
// Check the Login Status
        
$this->__checkFBStatus();
        
// publish the cookie
        
$this->set('FACEBOOK_APP_ID',$this->FACEBOOK_API_ID);
        
$this->set('FACEBOOK_COOKIE',$this->FACEBOOK_COOKIE);
   }
...
?>

Next we need to Integrate the Facebook Javascripts an the FBML definition into the layout default view.
You need to modify the Tag and add a new Javscript.

View Template:


<html  xmlns="http://www.w3.org/1999/xhtml"  xmlns:fb="http://www.facebook.com/2008/fbml">
...
<head>
...
<script src="https://connect.facebook.net/de_DE/all.js"></script>
</head>
...

The last step is to change you login view for example the login.ctp
In this view we add the new Functions to call the Login from the Facebook Connect.

View Template:


...
   <?php if (isset($FACEBOOK_COOKIE['uid'])) { ?>
             Your User ID is <?php echo $FACEBOOK_COOKIE['uid']; ?>
   <?php } else {
             <
fb:login-button v="2"><fb:intl>Connect with Facebook</fb:intl></fb:login-button>
   <?
php ?>

   <div id="fb-root"></div>
   <script>
       FB.init({appId: '<?php echo $FACEBOOK_API_ID?>', status: true,
               cookie: true, xfbml: true});
       FB.Event.subscribe('auth.login', function(response) {
                        window.location.reload();
       });
   </script>
...

That's it. Feel free to modify and use the code.... you can see the Code in action on
http://www.eventmanager-online.com an Online Eventmanager

Report

More on Tutorials

Advertising

Comments

  • fsiebler posted on 08/05/11 05:52:45 PM
    @Daniel, as i worte in my blog, the code is working, but looks like not on a Windows (WAMPP) Systems.
    And it's not working on a System witch is not online reachable. You need this because facebook can not set the cookie...(i think it's not working for local Domains like "stuff.local"...), you also need to tell facebook the App-Domain in the Facebook Application Setting.
  • danieln posted on 07/13/11 05:59:02 PM
    Hi,

    I have followed the code here and applied them on the app_controller.php & login.ctp, but when I run the login page I get an error "Fatal error: Can't use method return value in write context in /home/account/public_html/fb/app/app_controller.php on line 55"

    I did a look up on the line and it is pointing to "if (isset($this->Cookie->read('fbs_' . $app_id))) { "

    Anyone facing this sample problem? Or anyone got the codes working? hope you could help me out here. thanks a lot!!
  • rajan0302 posted on 02/28/11 09:21:41 AM
    private function __checkFBStatus(){
    $this->loadModel('User');
    //check to see if a user is not logged in, but a facebook user_id is set
    if(!$this->Auth->User() && $this->FACEBOOK_COOKIE) {
    ........

    Hi can some one please tell me what is the need of checking $this->Auth->User() everytime?
  • manas posted on 01/01/11 02:21:15 PM
    Fatal error: Can't use method return value in write context in C:\xampp\htdocs\social\app_controller.php on line 12

    On line 12, this block starts -
    if (isset($this->Cookie->read('fbs_' . $app_id))) {.........



  • sams posted on 05/23/10 06:59:29 PM
    First thanks for taking the time to put this article together, currently you are breaking a of Cakes coding standards eg:

    php short tags +missing semi-colons
    if statements without curly braces
    access $_COOKIE var rather than via the Cake Cookie Component

    https://trac.cakephp.org/wiki/Developement/CodingStandards
    these are easily correctable

    (also I amended a few parts of the article for English spelling and grammar)

    many thanks for you efforts - Sam
    • fsiebler posted on 05/26/10 07:53:35 AM
      Hello Sam,

      i changed the the "Bugs" :-)

      Thanks &
      Fabian

      First thanks for taking the time to put this article together, currently you are breaking a of Cakes coding standards eg:

      php short tags +missing semi-colons
      if statements without curly braces
      access $_COOKIE var rather than via the Cake Cookie Component

      https://trac.cakephp.org/wiki/Developement/CodingStandards
      these are easily correctable

      (also I amended a few parts of the article for English spelling and grammar)

      many thanks for you efforts - Sam
login to post a comment.