The situation: I have a finished Facebook canvas app (PHP/CodeIgniter), I just need to add the Facebook-related options such as sharing and inviting friends.
Current task: getting the list of invitable friends from the PHP SDK.
Relevant documentation: https://developers.facebook.com/docs/games/invitable-friends/v2.0
The code: in my Facebook library, I have created the following function.
/**
* Returns the current user's invitable friends
*/
public function get_invitable_friends() {
if ( $this->session ) {
$request = ( new FacebookRequest( $this->session, 'GET', '/me/invitable_friends' ) )->execute();
$graphObject = $request->getGraphObject();
return $graphObject;
}
return false;
}
The condition if($this->session) is because it doesn't make sense to try anything if there's no Facebook session in the first place. This will come into play later.
I've tried calling this function in two ways. The first way works and the second doesn't. I'm gonna present both, and then somebody will hopefully explain to me why the second way doesn't work and how to fix it, as I'd much prefer to use that.
First (working) way:
Call the function from the main controller's index() method, as the page loads. The function correctly returns a list of my friends.
Second (non-working) way:
Create this function in the controller:
//load list of friends we can invite to play the game
public function load_invitable_friends()
{
$this->load->library('facebook');
$list = $this->facebook->get_invitable_friends();
var_dump($list);
}
Then call it through AJAX, like:
function loadInvites(){
$.post(base+"main/load_invitable_friends/",function(resp){
$('#slide_6_inner').html(resp);
});
}
After this call, the content of the slide_6_inner div should contain the list of friends, as dumped by var_dump. However, the content is bool(false), indicating that the Facebook session is no longer present.
If I remove the condition if( $this->session ) from the get_invitable_friends() method, then this error happens:
A PHP Error was encountered
Severity: 4096
Message: Argument 1 passed to Facebook\FacebookRequest::__construct() must be an instance of Facebook\FacebookSession, null given, called in /home/lights/public_html/appname/application/libraries/facebook/Facebook.php on line 125 and defined
Filename: Facebook/FacebookRequest.php
Line Number: 182
The session in Facebook.php is initially created with the following code.
$this->ci =& get_instance();
// Initialize the SDK
FacebookSession::setDefaultApplication( $api_id, $api_secret) );
$this->helper = new FacebookCanvasLoginHelper();
$this->session = $this->helper->getSession();
To sum up - why is this problem occurring and how do I fix it?
In order to retrieve the session from the server side, you will need to first create a session using the FacebookCanvasLoginHelper. This class takes a signed request from Facebook supplied in a POST request, and exchanges it for a FacebookSession object. This should only really be done one when a user logs into your application:
$helper = new FacebookCanvasLoginHelper();
try {
$session = $helper->getSession();
} catch (FacebookRequestException $ex) {
// When Facebook returns an error
} catch (\Exception $ex) {
// When validation fails or other local issues
}
if ($session) {
// Store this in your PHP session somewhere:
$token = $session->getToken();
}
Thereafter, you should use the token to initialize the session:
$token = //GET THIS FROM SESSION
use Facebook\FacebookSession;
FacebookSession::setDefaultApplication('app-id', 'app-secret');
// If you already have a valid access token:
$session = new FacebookSession($token);
// To validate the session:
try {
$session->validate();
} catch (FacebookRequestException $ex) {
// Session not valid, Graph API returned an exception with the reason.
echo $ex->getMessage();
} catch (\Exception $ex) {
// Graph API returned info, but it may mismatch the current app or have expired.
echo $ex->getMessage();
}
Well, it seems you are not doing anything if session does not exists, just returning false. The problem is occuring because the session is expired/or does not exists, so you have to validate the fbToken and set the session again or create a new one.
You can create a function that checks if user is logged in, like:
function CheckFbUser() {
// Check if existing session exists
if (isset($_SESSION) && isset($_SESSION['fb_token'])) {
// Create new session from saved access_token
$session = new FacebookSession($_SESSION['fb_token']);
// Validate token
try {
if (!$session->validate()) {
$session = null;
}
} catch (Exception $e) {
// Catch any exceptions
$session = null;
}
} else {
// No session
try {
$session = $helper->getSessionFromRedirect();
} catch(FacebookRequestException $e) {
// handle it for facebook exceptions
} catch(Exception $e) {
// handle your php exceptions
}
}
// Check if a session exists
if ( isset( $session ) ) {
// Save the session
$_SESSION['fb_token'] = $session->getToken();
// Create session using saved token or the new one we generated at login
$session = new FacebookSession( $session->getToken() );
// USUALLY, here, people show the Logout Button, or anything alike, but you could it
// to return true, and then continue to run your code.
} else {
// No session
// USUALLY, here, people show the Login Button, or anything alike, you could
// use it to return false, or redirect user to login first.
$helper->getLoginUrl();
}
}
That is just an simple code, to check if user is logged in or not before you run the requests.
Related
I'm trying to figure out if a user is following another user on Soundcloud using the Soundcloud API and php.
So far I came across a solution which would either return an object (user) or a 404 error:
$test = json_decode($client->get('/users/{id1}/followers/{id2}'));
I've tried it multiple times with different user IDs but I always receive a the following error message:
'Services_Soundcloud_Invalid_Http_Response_Code_Exception' with message 'The requested URL responded with HTTP code 404.'
I know that this is supposed to be the error message which informs me that user2 is not following user1. However I've tried this snippet with ids where I know a reciprocal following exists for sure.
Any suggestions on how this can be solved?
Update (21.05.15):
I've read through some of the Soundcloud documentation and cam across a code snippet:
<?php
require_once 'Services/Soundcloud.php';
// create a client object with access token
$client = new Services_Soundcloud('YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET');
$client->setAccessToken('YOUR_ACCESS_TOKEN');
// Follow user with ID 3207
$client->put('/me/followings/3207');
// Unfollow the same user
$client->delete('/me/followings/3207');
// check the status of the relationship
try {
$client->get('/me/followings/3207');
} catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e) {
if ($e->getHttpCode() == '404')
print "You are not following user 3207\n";
}
?>
This is pretty much what I was referring to. However if I open a php page with this script the result is always one of three cases:
You are not following user 3207 (expected output)
No output (I'm following the user)
Uncaught exception 'Services_Soundcloud_Invalid_Http_Response_Code_Exception' with message 'The requested URL responded with HTTP code 404.'
The third option is either referring to $client->put or $client->delete
Here is how i would do this:
<?php
require_once 'Services/Soundcloud.php';
$client = new Services_Soundcloud(
'xxxxxxxxxxxxxxxxxxx160', 'xxxxxxxxxxxxxxxxxx34dd1 ');
$userid = 1672444;
$followerid = 383228;
$yesno = '';
try {
$response = json_decode($client->get('users/'.$userid.'/followers'), true);
$yesno = IdInArray($response, $followerid);
echo $yesno;
} catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e) {
exit($e->getMessage());
}
function IdInArray($response, $followerid){
echo $followerid.'<br/>';
for($i = 0; $i < count($response); ++$i) {
if($response[$i]['id'] == $followerid){
return 'yolo';
}
else{
return 'nolo';
}
}
}
?>
I'm trying to read ratings from a Facebook page to display externally, using the PHP SDK. I already have a long live access token, and have been able to use it to pull in the main page data, but when I try access the /ratings endpoint, I just receive back an empty Array ( )
class FacebookReviews
{
protected $session;
protected $page;
protected $ratings;
protected $appId;
protected $appSecret;
function __construct($appId = null, $appSecret = null)
{
session_start();
$this->appId = '123456789123456';
$this->appSecret = '1234567890abcdefghijklmnopqrstuv';
Facebook\FacebookSession::setDefaultApplication($this->appId, $this->appSecret);
$this->session = new Facebook\FacebookSession('LONG LIVE ACCESS TOKEN I GENERATED ON THE GRAPH API');
try {
$this->session->validate();
} catch (Facebook\FacebookRequestException $ex) {
// Session not valid, Graph API returned an exception with the reason.
echo $ex->getMessage();
} catch (\Exception $ex) {
// Graph API returned info, but it may mismatch the current app or have expired.
echo $ex->getMessage();
}
try {
$this->page = (new Facebook\FacebookRequest($this->session, 'GET', '/123456789123456/ratings'))->execute()->getGraphObject()->asArray();
} catch(Facebook\FacebookRequestException $e) {
echo "Exception occured, code: " . $e->getCode();
echo " with message: " . $e->getMessage();
}
}
public function result()
{
return $this->page;
}
}
$reviews = new FacebookReviews();
print_r($reviews->result());
If I remove /ratings from the request uri, it returns the data fine, but as I mentioned with it in there it doesn't work.
I generated the long live access token from my own account, which has admin access to the page
I am attempting to retrieve the number of fans for my Page via the PHP SDK. Here is all of my code so far.
$fbSession = \Facebook\FacebookSession::newAppSession(self::APP_ID, self::APP_SECRET);
$fbLikesResponse = null;
try {
$fbLikesRequest = new \Facebook\FacebookRequest($fbSession, 'GET', '/{myRealPageIDGoesHere}/insights/page_fans');
$fbLikesResponse = $fbLikesRequest->execute()->getGraphObject()->asArray();
} catch (\Facebook\FacebookRequestException $ex) {
$resp = new \stdClass();
$resp->error = $ex;
return $resp;
} catch (\Exception $ex) {
echo $ex->getMessage();
}
//Add items to response and to store
var_dump($fbLikesResponse);
I never get authentication/authorizaiton errors, but the data response value is always just 0. I can see on the Facebook page itself that there are more than 0 likes.
I really don't want to have to resort to screen-scraping to obtain how many likes my Facebook page has. Any idea why I only get 0s?
Clarification- this is for a server-side call for an analytics engine. No user authentication is involved, so I'm trying to figure out how to get hit the {node}/insights/page_fans endpoint without faking some sort of user login.
I am able to login with user credentials with
try {
$user = ParseUser::logIn("myname", "mypass");
// Do stuff after successful login.
} catch (ParseException $error) {
// The login failed. Check error to see why.
}
but if I try to get the currentUser afterwards with
$currentUser = ParseUser::getCurrentUser();
if ($currentUser) {
// do stuff with the user
} else {
// show the signup or login page
}
$currentUser is not set.
I suspect this more to be a php "issue" that I don't know. I am greatful for any hint for keeping currentUser retained in my code as long I do not log out.
In order for the getCurrentUser() method to work, you must define the type of session storage to use. You can use the ParseSessionStorage class to achieve this:
use Parse\ParseClient;
use Parse\ParseUser;
use Parse\ParseSessionStorage;
session_start();
// Init parse: app_id, rest_key, master_key
ParseClient::initialize('xxx', 'yyy', 'zzz');
// set session storage
ParseClient::setStorage( new ParseSessionStorage() );
try {
$user = ParseUser::logIn("myname", "mypass");
// Do stuff after successful login.
} catch (ParseException $error) {
// The login failed. Check error to see why.
}
$currentUser = ParseUser::getCurrentUser();
print_r( $currentUser );
I have all of the files (facebook.php, base_facebook.php, index.php) in the same directory. My server(s) are Apache, and both support php.
My code:
<html>
<body>
<?php
try
{
echo("STARTING<br>");
require("facebook.php");
}
catch(Exception $e)
{
echo("ERROR1: $e");
}
try
{
$facebook = new Facebook("***","###");
}
catch(Exception $e)
{
echo("ERROR2: $e");
}
$token = $facebook->getAccessToken();
echo("Access token: ".$token."<br>");
My text output is as follows:
STARTING
ERROR1: Object id #1before create fb instance
Fatal error: Class 'Facebook' not found in /(FILE PATH)/index.php on line 16
Note: line 16 is: $facebook = new Facebook("***","###");
The first catch statement is printing: Object Id #1. Then it does my next print statement. Then it returns Fatal Error that is not caught. What am I missing here?
Why can the server not get the correct access token?
You failed to require the facebook.php, hence the ERROR1: Object id #1 - you're trying to echo out the exception error object. Try
catch ($e) {
die($e->getMessage());
}
instead.
You should not catch that kind of error. if a require fails, the only useful solution is to abort execution, because you've not gotten what you REQUIRED to continue execution.
Basically you've implemented a PHPized version of visual basic's on error resume next, with all the nasty stupidity that goes with it.
You should put the code before the header is sent :
Go here for further information : https://developers.facebook.com/docs/reference/php/
Basically, put this on very on top of your code :
<?php
require_once("facebook.php");
$config = array();
$config[‘appId’] = 'YOUR_APP_ID';
$config[‘secret’] = 'YOUR_APP_SECRET';
$config[‘fileUpload’] = false; // optional
$facebook = new Facebook($config);
?>
Then load your HTML (In MVC style will be better for maintenance ;-)