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?
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 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');
}
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>';
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With