Integrate the Facebook Platform into your Symfony2 application.
PHP
Pull request Compare This branch is 1 commit ahead, 372 commits behind FriendsOfSymfony:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
Command
DependencyInjection
Resources
Security
Templating/Helper
Tests
Twig/Extension
.gitignore
FOSFacebookBundle.php
README.md
phpunit.xml.dist

README.md

Installation

  1. Add this bundle to your src/ dir and the Facebook PHP SDK to your vendor/ dir:

      $ git submodule add git://github.com/FriendsOfSymfony/FacebookBundle.git src/FOS/FacebookBundle
      $ git submodule add git://github.com/facebook/php-sdk.git vendor/facebook
    
  2. Add the FOS namespace to your autoloader:

      // app/autoload.php
      $loader->registerNamespaces(array(
            'FOS' => __DIR__.'/../src',
            // your other namespaces
      ));
    
  3. Add this bundle to your application's kernel:

      // app/ApplicationKernel.php
      public function registerBundles()
      {
          return array(
              // ...
              new FOS\FacebookBundle\FOSFacebookBundle(),
              // ...
          );
      }
    
  4. Configure the facebook service in your config:

      # application/config/config.yml
      fos_facebook.api:
          file:   %kernel.root_dir%/../vendor/facebook/src/facebook.php
          alias:  facebook
          app_id: 123456879
          secret: s3cr3t
          cookie: true
    
      # application/config/config.xml
      <fos_facebook:api
          file="%kernel.root_dir%/../vendor/facebook/src/facebook.php"
          alias="facebook"
          app_id="123456879"
          secret="s3cr3t"
          cookie="true"
      />
    

    If you do not include a file value in the config you will have to configure your application to autoload the Facebook class.

  5. Add this configuration if you want to use the security component:

      # application/config/config.yml
      security.config:
          factories:
              - "%kernel.root_dir%/../src/FOS/FacebookBundle/Resources/config/security_factories.xml"
    
          providers:
              fos_facebook:
                id: fos_facebook.auth
    
          firewalls:
              public:
                  pattern:   /.*
                  fos_facebook:  true
                  anonymous: true
    
              only_facebook: # with facebook entry point (redirect to the facebook login url)
                  pattern:   /only_facebook/.*
                  fos_facebook:  true
    
          access_control:
              - { path: /.*, role: [ROLE_USER, IS_AUTHENTICATED_ANONYMOUSLY] }
    
  6. Optionally define a custom user provider class and use it as the provider or define path for login

      # application/config/config.yml
      security.config:
          factories:
                - "%kernel.root_dir%/../src/FOS/FacebookBundle/Resources/config/security_factories.xml"
    
          providers:
              fos_facebook:
                id: fos_facebook.user_provider
    
          firewalls:
              public:
                  pattern:   /.*
                  fos_facebook:
                      login_path: /facebook
                      check_path: /facebook-check
                      default_target_path: /facebook
                      provider: fos_facebook
                  anonymous: true
    

Setting up the JavaScript SDK

A templating helper is included for loading the Facebook JavaScript SDK and initializing it with parameters from your service container. To setup the Facebook JavaScript environment, add the following to your layout just after the opening body tag:

  <body>
      <!-- inside a php template -->
      <?php echo $view['facebook']->initialize(array('xfbml' => true)) ?>
      <!-- inside a twig template -->
      {{ facebook_initialize({'xfbml': true}) }}

If you will be adding XFBML markup to your site you may also declare the namespace, perhaps in the opening html tag:

  <html xmlns:fb="http://www.facebook.com/2008/fbml">

Include the login button in your templates

Just add the following code in one of your templates:

<!-- inside a php template -->
<?php echo $view['facebook']->loginButton(array('autologoutlink' => true)) ?>
<!-- inside a twig template -->
{{ facebook_login_button({'autologoutlink': true}) }}

Example Customer User Provider using the FOS\UserBundle

This requires adding a getFacebookId() and setFBData() method to the User model.

<?php

namespace Foo\BarBundle\Security\User\Provider;

use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedAccountException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\AccountInterface;
use \Facebook;
use \FacebookApiException;

class FacebookProvider implements UserProviderInterface
{
    /**
     * @var \Facebook
     */
    protected $facebook;
    protected $userManager;
    protected $validator;

    public function __construct(Facebook $facebook, $userManager, $validator)
    {
        $this->facebook = $facebook;
        $this->userManager = $userManager;
        $this->validator = $validator;
    }

    public function supportsClass($class)
    {
        return $this->userManager->supportsClass($class);
    }

    public function findUserByFbId($fbId)
    {
        return $this->userManager->findUserBy(array('facebookID' => $fbId));
    }

    public function loadUserByUsername($username)
    {
        $user = $this->findUserByFbId($username);

        try {
            $fbdata = $this->facebook->api('/me');
        } catch (FacebookApiException $e) {
            $fbdata = null;
        }

        if (!empty($fbdata)) {
            if (empty($user)) {
                $user = $this->userManager->createUser();
                $user->setEnabled(true);
                $user->setPassword('');
                $user->setAlgorithm('');
            }

            // TODO use http://developers.facebook.com/docs/api/realtime
            $user->setFBData($fbdata);

            if (count($this->validator->validate($user, 'Facebook'))) {
                // TODO: the user was found obviously, but doesnt match our expectations, do something smart
                throw new UsernameNotFoundException('The facebook user could not be stored');
            }
            $this->userManager->updateUser($user);
        }

        if (empty($user)) {
            throw new UsernameNotFoundException('The user is not authenticated on facebook');
        }

        return $user;
    }

    public function loadUserByAccount(AccountInterface $account)
    {
        if (!$this->supportsClass(get_class($account)) || !$account->getFacebookId()) {
            throw new UnsupportedAccountException(sprintf('Instances of "%s" are not supported.', get_class($account)));
        }

        return $this->loadUserByUsername($account->getFacebookId());
    }
}