質問

I wanted implement the new facebook API v 4.0.0 on my project laravel.

Setting all the necessary informations and credentials for access to my app, when is time to call the function for the login:

$helper = new FacebookRedirectLoginHelper('http://mywebsite.dev');
$loginUrl = $helper->getLoginUrl();

It throw me an exception

FacebookSDKException 'Session not active, could not store state.'

So I dig in to the SDK class of facebook on that line and there is a check about session precisely this one:

 if (session_status() !== PHP_SESSION_ACTIVE) {
      throw new FacebookSDKException(
        'Session not active, could not store state.'
      );
    }

Then I didn't know why this happen so i tried to put the same check on a clean route and see the result

Route::get('test',function() {

   if (session_status() !== PHP_SESSION_ACTIVE)
    {
        return "is not active";
    }

    return "is active";

});

And it return is not active why this happen? in this way I cannot use the new facebook API with laravel?

役に立ちましたか?

解決 2

I solve extending that class and overwriting the following 2 methods that require native sessions.

    protected function storeState($state)
    {
        Session::put('facebook.state', $state);
    }

    protected function loadState()
    {
        return $this->state =  Session::get('facebook.state');
    }

他のヒント

Sharing how I implemented Facebook SDK V4 on Laravel 4.

Here's what I added on default composer.json

"autoload": {
    "classmap": [
        "app/commands",
        "app/controllers",
        "app/models",
        "app/database/migrations",
        "app/database/seeds",
        "app/tests/TestCase.php"
    ],
    "psr-4" : {
        "Facebook\\":"vendor/facebook/php-sdk-v4/src/Facebook/"
    }
},

Added Facebook initialization on my index.php, like this :

/*
|--------------------------------------------------------------------------
| Initialized Facebook PHP SDK V4
|--------------------------------------------------------------------------
|
*/

//Initialize
use Facebook\FacebookSession;
FacebookSession::setDefaultApplication(Config::get('facebook.AppId'),Config::get('facebook.AppSecret'));

And for the Session, Laravel doesn't use $_SESSION so you don't need to do session_start at all. For you to be able to use Laravel session on Facebook PHP SDK V4, you need to extend Facebook's FacebookRedirectLoginHelper class. Here's how how to subclass FacebookRedirectLoginHelper and overwrite Session handling.

class LaravelFacebookRedirectLoginHelper extends \Facebook\FacebookRedirectLoginHelper
{

  protected function storeState($state)
  {
    Session::put('state', $state);
  }

  protected function loadState()
  {
    $this->state = Session::get('state');
    return $this->state;
  }


  protected function isValidRedirect()
  {

    return $this->getCode() && Input::has('state')
        && Input::get('state') == $this->state;

  }



  protected function getCode()
  {
    return Input::has('code') ? Input::get('code') : null;
  }


  //Fix for state value from Auth redirect not equal to session stored state value
  //Get FacebookSession via User access token from code
  public function getAccessTokenDetails($app_id,$app_secret,$redirect_url,$code)
  {

        $token_url = "https://graph.facebook.com/oauth/access_token?"
          . "client_id=" . $app_id . "&redirect_uri=" . $redirect_url
          . "&client_secret=" . $app_secret . "&code=" . $code;

        $response = file_get_contents($token_url);
        $params = null;
        parse_str($response, $params);

        return $params;
   }


}

And one more step, you need to do a composer command to regenerate autoload files :

composer dump-autoload -o

Ok, if all goes right, you are now ready to start using the SDK, here's a sample

Here's an excerpt from one of my project classes :

namespace Fb\Insights;

//Facebook Classes
use Facebook\FacebookSession;
use Facebook\FacebookRequest;
use Facebook\FacebookSDKException;


//Our Facebook Controller
use FbController;

class PagePosts extends \Facebook\GraphObject {

    /*
        Get Page Posts Impression
        https://developers.facebook.com/docs/graph-api/reference/v2.0/insights#post_impressions     


    */
    public static function getPagePostsImpressions($postid = null) {

        $fbctrl = new FbController();

        $metricNames = array(
            'post_impressions',
            'post_impressions_unique',
            'post_impressions_paid',
            'post_impressions_paid_unique',
            'post_impressions_fan',
            'post_impressions_fan_unique',
            'post_impressions_fan_paid',
            'post_impressions_fan_paid_unique',
            'post_impressions_organic',
            'post_impressions_organic_unique',
            'post_impressions_viral',
            'post_impressions_viral_unique',
            'post_impressions_by_story_type',
            'post_impressions_by_story_type_unique',
            'post_impressions_by_paid_non_paid',
            'post_impressions_by_paid_non_paid_unique'
        );

        $postsInsights = array();       
        $batch = array();
        $limit = $fbctrl->FacebookGraphDateLimit();     


        //craft our batch API call
        for($i=0; $i<count($metricNames); $i++) {       
            $batch[] = json_encode(array('method' => 'GET','relative_url' => $postid . '/insights/' . $metricNames[$i] . '?since=' . $limit['since'] . '&until=' . $limit['until'] ));
        }
        $params = array( 'batch'    => '[' . implode(',',$batch ) . ']' );      

        $session = new FacebookSession($fbctrl->userAccessToken);

        try {

            $res = (new FacebookRequest($session,'POST','/',$params))
                ->execute()
                ->getGraphObject();

        } catch(FacebookRequestException $ex) {
            //log this error
            echo $ex->getMessage();
        } catch(\Exception $ex) {
            //log this error
            echo $ex->getMessage();
        }

        //Collect data
        for($i=0; $i<count($batch); $i++) {

            $resdata = json_decode(json_encode($res->asArray()[$i]),true);

            $fbctrl->batchErrorDataChecker($resdata,$postsInsights,$metricNames[$i]);

        }

        return $postsInsights;

    }

Feel free comment or suggest so I can also improve my code. Happy coding.

I used follow steps using Composer and had problem "Session not active, could not store state" so session_start() fixed my issue.

require_once './vendor/autoload.php';

use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;

session_start();
FacebookSession::setDefaultApplication('apid', 'appscret');
$helper = new FacebookRedirectLoginHelper("callbackurl", $apiVersion = NULL);
try {
    $session = $helper->getSessionFromRedirect();
} catch (FacebookRequestException $ex) {
    // When Facebook returns an error
} catch (\Exception $ex) {
    // When validation fails or other local issues
}
if (isset($session)) {

    $request = new FacebookRequest($session, 'GET', '/me');
    $response = $request->execute();
    $graphObject = $response->getGraphObject();
    var_dump($graphObject);
} else {
    echo '<a href="' . $helper->getLoginUrl() . '">Login with Facebook</a>';
}

To solve problem call session_start php function after to inizialize FacebookRedirectLoginHelper somthing like this:

session_start();

$helper = new FacebookRedirectLoginHelper('http://mywebsite.dev');

$loginUrl = $helper->getLoginUrl();

kaixersoft's answer really saved my bacon a little while ago, and I got everything to work by following his instructions using the custom LaravelFacebookRedirectLoginHelper class. But today I went to do a 'composer update' and for some reason, it broke everything. I've modified kaixersoft's LaravelFacebookRedirectLoginHelper class so that it works now, specifically the isValidRedirect method. Here is the updated class:

class LaravelFacebookRedirectLoginHelper extends \Facebook\FacebookRedirectLoginHelper
{

  protected function storeState($state)
  {
    Session::put('state', $state);
  }

  protected function loadState()
  {
    $this->state = Session::get('state');
    return $this->state;
  }


  protected function isValidRedirect()
  {
    $savedState = $this->loadState();
    if (!$this->getCode() || !isset($_GET['state'])) {
      return false;
    }
    $givenState = $_GET['state'];
    $savedLen = mb_strlen($savedState);
    $givenLen = mb_strlen($givenState);
    if ($savedLen !== $givenLen) {
      return false;
    }
    $result = 0;
    for ($i = 0; $i < $savedLen; $i++) {
      $result |= ord($savedState[$i]) ^ ord($givenState[$i]);
    }
    return $result === 0;
  }



  protected function getCode()
  {
    return Input::has('code') ? Input::get('code') : null;
  }


  //Fix for state value from Auth redirect not equal to session stored state value
  //Get FacebookSession via User access token from code
  public function getAccessTokenDetails($app_id,$app_secret,$redirect_url,$code)
  {

        $token_url = "https://graph.facebook.com/oauth/access_token?"
          . "client_id=" . $app_id . "&redirect_uri=" . $redirect_url
          . "&client_secret=" . $app_secret . "&code=" . $code;

        $response = file_get_contents($token_url);
        $params = null;
        parse_str($response, $params);

        return $params;
   }


}

session_status function is available on (PHP >=5.4.0) version. So if you are using older version of PHP then Please update it Or Just

 // change this 

 if (session_status() !== PHP_SESSION_ACTIVE) {

      throw new FacebookSDKException(
        'Session not active, could not store state.'
      );
    }



//into this

if(session_id() === "") {

    throw new FacebookSDKException(
        'Session not active, could not load state.'
    );
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top