An elegant and efficient way to interface with Facebook's Graph API using the latest Facebook PHP SDK v4. It's as easy as:
$user = $fqb->object('me')->get();
- Installation
- Usage
- Overwriting Persistent Storage
- Testing
- TODO
- Contributing
- CHANGELOG
- Credits
- License
Facebook Query Builder is installed using Composer. Add the Facebook Query Builder package to your composer.json
file.
{
"require": {
"sammyk/facebook-query-builder": "~1.1"
}
}
Or via the command line in the root of your project installation.
$ composer require "sammyk/facebook-query-builder:~1.1"
After creating an app in Facebook, you'll need to provide the app ID and secret.
use SammyK\FacebookQueryBuilder\FQB;
FQB::setAppCredentials('your_app_id', 'your_app_secret');
$fqb = new FQB();
Most calls to Graph require an access token. There are three ways to obtain an access token.
Access tokens are returned in the form of an AccessToken
object.
The most common way to obtain an access token is to provide a login URL and get the access token on the specified callback URL.
$login_url = $fqb->auth()->getLoginUrl('http://my-callback/url');
Then in the callback URL you can obtain the access token.
use SammyK\FacebookQueryBuilder\FacebookQueryBuilderException;
try
{
$token = $fqb->auth()->getTokenFromRedirect('http://my-callback/url');
}
catch (FacebookQueryBuilderException $e)
{
// Failed to obtain access token
echo 'Error:' . $e->getMessage();
}
You can optionally send in an array of permissions to request.
$scope = ['email', 'user_status'];
$login_url = $fqb->auth()->getLoginUrl('http://my-callback/url', $scope);
See a full example of obtaining an access token from redirect.
If you are running your app from within the context of an app canvas, you can try to obtain an access token from the signed request that Facebook sends to your app.
use SammyK\FacebookQueryBuilder\FacebookQueryBuilderException;
try
{
$token = $fqb->auth()->getTokenFromCanvas();
}
catch (FacebookQueryBuilderException $e)
{
// Failed to obtain access token
echo 'Error:' . $e->getMessage();
}
If you are using the Javascript SDK on your site, FQB can obtain an access token from the signed request that the Javascript SDK sets in the cookie.
use SammyK\FacebookQueryBuilder\FacebookQueryBuilderException;
try
{
$token = $fqb->auth()->getTokenFromJavascript();
}
catch (FacebookQueryBuilderException $e)
{
// Failed to obtain access token
echo 'Error:' . $e->getMessage();
}
By default access tokens will last for about 2 hours. You can exchange them for longer-lived tokens that last for about 60 days.
See a full example in the obtaining an access token from redirect example file.
if ( ! $access_token->isLongLived())
{
// Extend the short-lived token
}
try
{
$long_lived_token = $short_lived_token->extend();
}
catch (FacebookQueryBuilderException $e)
{
// Failed to extend access token
echo 'Error:' . $e->getMessage();
}
try
{
$token_info = $access_token->getInfo();
}
catch (FacebookQueryBuilderException $e)
{
// Failed to get access token info
echo 'Error:' . $e->getMessage();
}
Setting the access token will new up a FacebookSession
internally and automatically send it with all Graph calls.
You can set the access token from a string or an AccessToken
object.
FQB::setAccessToken('access_token');
// -- OR --
FQB::setAccessToken($access_token_object);
Alternatively, if you already have a FacebookSession
object directly from the Facebook SDK, you can set it like so:
FQB::setFacebookSession($facebook_session);
Get the logged in user's profile.
$user = $fqb->object('me')->fields('id','email')->get();
Get info from a Facebook page.
$page = $fqb->object('facebook_page_id')->fields('id','name','about')->get();
Facebook Query Builder supports nested requests so you can get a lot more data with just one call to Graph.
Note: Facebook calls endpoints on the Graph API "edges". This package adopts the same nomenclature.
The following example will get the logged in user's name & first 5 photos they are tagged in with just one call to Graph.
$photos = $fqb->edge('photos')->fields('id', 'source')->limit(5);
$user = $fqb->object('me')->fields('name', $photos)->get();
And edges can have other edges embedded in them to allow for infinite deepness. This allows you to do fairly complex calls to Graph while maintaining very readable code.
The following example will get a user's name, and first 10 photos they are tagged in. For each photo get the first 2 comments and all the likes.
$likes = $fqb->edge('likes');
$comments = $fqb->edge('comments')->fields('message')->limit(2);
$photos = $fqb->edge('photos')->fields('id', 'source', $comments, $likes)->limit(10);
$user = $fqb->object('user_id')->fields('name', $photos)->get();
Check out the /examples directory to see more detailed examples.
To get the examples to work you'll need to duplicate the /examples/config.php.dist
to /examples/config.php
and enter your app credentials and access token.
Returns a new instance of the FQB
factory. Any valid Graph edge can be passed to object()
.
Performs a GET
request to Graph and returns the response in the form of a collection. Will throw an FacebookQueryBuilderException
if something went wrong while trying to communicate with Graph.
// Get the logged in user's profile
$user = $fqb->object('me')->get();
// Get a list of test users for this app
$test_users = $fqb->object('my_app_id/accounts/test-users')->get();
Sends a POST
request to Graph and returns the response in the form of a collection. Will throw an FacebookQueryBuilderException
if something went wrong while trying to communicate with Graph.
// Update a page's profile
$new_about_data = ['about' => 'This is the new about section!'];
$response = $fqb->object('page_id')->with($new_about_data)->post();
// Like a photo
$response = $fqb->object('photo_id/likes')->post();
// Post a status update for the logged in user
$data = ['message' => 'My witty status update.'];
$response = $fqb->object('me/feed')->with($data)->post();
$status_update_id = $response['id'];
// Post a comment to a status update
$comment = ['message' => 'My witty comment on your status update.'];
$response = $fqb->object('status_update_id/comments')->with($comment)->post();
Sends a DELETE
request to Graph and returns the response in the form of a collection. Will throw an FacebookQueryBuilderException
if something went wrong while trying to communicate with Graph.
// Delete a comment
$response = $fqb->object('comment_id')->delete();
// Unlike a photo
$response = $fqb->object('photo_id/likes')->delete();
Returns an Edge
value object to be passed to the fields()
method.
Set the fields and edges for this Edge
. The fields and edges can be passed as an array or list of arguments.
$edge_one = $fqb->edge('my_edge')->fields('my_field', 'my_other_field');
$edge_two = $fqb->edge('my_edge')->fields(['field_one', 'field_two']);
$obj = $fqb->object('some_object')->fields('some_field', $edge_one, $edge_two)->get();
Limit the number of results returned from Graph.
$edge = $fqb->edge('some_list_edge')->limit(7);
The array should be an associative array. The key should be the name of the field as defined by Facebook.
If used in conjunction with the post()
or delete()
methods, the data will be sent in the body of the request.
// Post a new comment to a photo
$comment_data = ['message' => 'My new comment!'];
$response = $fqb->object('photo_id')->with($comment_data)->post('comments');
// Update an existing comment
$comment_data = ['message' => 'My updated comment.'];
$response = $fqb->object('comment_id')->with($comment_data)->post();
If used in conjunction with a get()
request, the data will be appended in the URL either in the sub edge or root edge.
// Get the large version of a page profile picture
$profile_picture = $fqb->edge('picture')->with(['type' => 'large']);
$page_info = $fqb->object('some_page_id')->fields('name', $profile_picture)->get();
You can easily search Graph with the search()
method.
The first argument is your search query. The second argument is the optional type of Graph object you are searching for. See the Facebook documentation for a full list of supported search objects.
// Search for users named Bill
$list_of_users = $fqb->search('Bill', 'user')->get();
// Search for coffee joints near San Fransisco
$list_of_locations = $fqb->search('coffee', 'place')
->with([
'center' => '37.76,-122.427',
'distance' => '1000'
])
->get();
See more search examples.
Requests sent to Graph are represented by 2 value objects, RootEdge
& Edge
. Each object represents a segment of the URL that will eventually be compiled, formatted as a string, and sent to Graph with either the get()
or post()
method.
For debugging, you can access RootEdge
as a string to get the URL that will be sent to Graph.
$root_edge = $fqb->object('me')->fields('id', 'email');
echo $root_edge;
The above example will output:
/me?fields=id,email
An Edge
has the same properties as a RootEdge
but it will be formatted using nested-request syntax when it is converted to a string.
$photos = $fqb->edge('photos')->fields('id', 'source')->limit(5);
echo $photos;
The above example will output:
photos.limit(5).fields(id,source)
Edge
's can be embedded into other Edge
's.
$photos = $fqb->edge('photos')->fields('id', 'source')->limit(5);
$root_edge = $fqb->object('me')->fields('email', $photos);
echo $root_edge;
The above example will output:
/me?fields=email,photos.limit(5).fields(id,source)
All responses from Graph are returned as a collection object that has many useful methods for playing with the response data.
$user = $fqb->object('me')->fields('email', 'photos')->get();
// Access properties like an array
$email = $user['email'];
// Get data as array
$user_array = $user->toArray();
// Get data as JSON string
$user_json = $user->toJson();
// Iterate through the values
foreach ($user['photos'] as $photo) {
// . . .
}
// Morph the data with a closure
$user['photos']->each(function ($value) {
$value->new_height = $value->height + 22;
});
Check out the Collection class for the full list of methods.
The GraphObject
collection represents any set of data Graph would consider an "object". This could be a user, page, photo, etc. When you request an object by ID from Graph, the response will be returned as a GraphObject
collection.
$my_graph_object = $fqb->object('object_id')->get();
GraphObject
's can also contain GraphCollection
's if you request an edge in the fields list.
$my_graph_object = $fqb->object('object_id')->fields('id','likes')->get();
$my_graph_collection = $my_graph_object['likes'];
All datetime types on a GraphObject
will be automatically cast as Carbon
objects making datetime formatting/manipulation super easy.
$photo = $fqb->object('some_photo_id')->fields('name', 'created_time')->get();
echo 'Photo added ' . $photo['created_time']->diffForHumans();
The above example will output:
Photo added 4 days ago
The GraphCollection
collection is a collection of GraphObject
's.
$my_graph_collection = $fqb->object('me/statuses')->get();
If Graph returns an error, the response will be cast as a GraphError
collection and a FacebookQueryBuilderException
will be thrown.
try
{
$statuses = $fqb->object('me/statuses')->limit(10)->get();
}
catch (FacebookQueryBuilderException $e)
{
$graph_error = $e->getResponse();
echo 'Oops! Graph said: ' . $graph_error['message'];
}
If you try to use the getLoginUrl()
or getTokenFromRedirect()
and you're getting a FacebookSDKException
with the following error:
Session not active, could not store state.
Then you've fallen victim to the annoying persistent data storage issue that hasn't been fixed yet. So you'll need to implement your own class that overwrites the persistent storage found in the \Facebook\FacebookRedirectLoginHelper
.
For example a Laravel implementation would look like the following.
class LaravelFacebookRedirectLoginHelper extends \Facebook\FacebookRedirectLoginHelper
{
protected function storeState($state)
{
Session::put('state', $state);
}
protected function loadState()
{
return $this->state = Session::get('state');
}
}
FQB::setRedirectHelperAlias('LaravelFacebookRedirectLoginHelper');
Just run phpunit
from the root directory of this project.
$ phpunit
Future developments:
- Batch requests
$res = $fqb->batch(function($fqb) {
$fqb->object('user_id')->get();
$fqb->object('page_id')->fields('name', 'about')->get();
});
- Pagination on
GraphCollection
objects
Please see CONTRIBUTING for details.
Please see CHANGELOG for history.
The MIT License (MIT). Please see License File for more information.