-
Notifications
You must be signed in to change notification settings - Fork 33
Home
- Dependencies
- Usage and examples
- Efficiently using asynchronous curl
- Creating an OAuth application on Foursquare
Foursquare-async lets you easily integrate with Foursquare’s 2.0 REST API using OAuth2. In addition to being easy to use, it supports asynchronous calls.
- PHP 5.2 or higher
- EpiFoursquare and EpiCurl (included with the repository)
Some of the Foursquare API endpoints require authentication while others don’t. For authenticated API calls you can provide credentials using either basic authentication or OAuth. Basic authentication requires that you send the username and password of the account you want to use. OAuth let’s you pass tokens, instead of passwords, to make authenticated calls. Foursquare-async makes it easy by exposing an extremely simple API.
-
get($endpoint[, $params])
– GET request using OAuth 2 -
post($endpoint[, $params])
– POST request using OAuth 2 -
delete($endpoint[, $params])
– DELETE request using OAuth 2
// Calls which do not require authentication
$fsObj = new EpiFoursquare();
$venues = $fsObj->get_basic('/users/search', array('twitter' => 'naveen'));
echo $venues->responseText;
// Calls requiring authentication
$fsObj = new EpiFoursquare($clientId, $clientSecret, $accessToken);
$checkin = $fsObj->get('/checkins/add', array('venueId' => '35610', 'broadcast' => 'public'));
echo $checkin->responseText;
Once you’ve got your OAuth application the first thing you’ll want to do is the dance to get access tokens. You do this in several steps.
- Get an authorization url and have the user click on it
- The user is taken to Foursquare’s site and clicks “Allow”
- The user is then redirected back to your callback url
- You exchange the request token for an access token and save it for future calls
An example of step one looks like this.
$fsObj = new EpiFoursquare($clientId, $clientSecret);
// $redirectUrl is what you specified when creating the application
$url = $fsObj->getAuthorizeUrl($redirectUrl);
echo "<a href=\"$url}\">Click here</a>";
// part of the response includes an oauth_token_secret you want to save for step 4
Once the user clicks “Allow” they are redirected back to your callback URL along with a code in the query string. You can use the code to obtain an access token that you should save (salted and encrypted, of course) to make authenticated calls in the future.
$fsObj = new EpiFoursquare($clientId, $clientSecret);
// exchange the request token for an access token
$token = $fsObj->getAccessToken($_GET['code'], $redirectUrl);
// you can store $token->access_token in your database
$fsObj->setAccessToken($token->access_token);
$res = $fsObj->get('/checkins/add', array('venueId' => '12345', 'broadcast' => 'public'));
var_dump($res->result);
All calls to Foursquare’s API return an object with properties. The properties are named identical to what is in the response and dimensions of 2 or more are exposed as arrays. For example, the following JSON response is from the users/USER_ID/badges API (<http://developer.foursquare.com/docs/users/badges.html>.
{
meta: { code: 200 },
response: {
// most of the data you want is here
}
}
Each of these values can be accessed the following ways.
// Access properties directly as member variables
$userInfo->screen_name;
$userInfo->name;
$userInfo->status->text;
$userInfo->status->created_at;
// Access properties as an array through the response property
$userInfo->response['screen_name'];
$userInfo->response['name'];
$userInfo->response['status']['text'];
$userInfo->response['status']['created_at'];
You can access the response headers for your request by checking the $resp->headers
array.
$resp = $fsObj->get_search(array('q' => 'twitter'));
var_dump($resp->headers);
echo "You have {$resp->headers['X-RateLimit-Remaining']} calls remaining";
Some responses are returned as an enumerated list. Since PHP requires that object properties start with [a-Z_] you can’t use $resp->0->screen_name
. Given the following JSON response, you can use either of the methods described below.
[
{
screen_name: "jmathai",
name: "Jaisen Mathai"
...
},
{
screen_name: "jmathai",
name: "Jaisen Mathai"
...
},
...
]
// Access the respose as an array
$firstFollower = $resp[0]->screen_name
// Loop over the response as an an array
foreach($resp as $follower){
echo $follower->screen_name;
}
Foursquare-async throws an exception anytime the HTTP response code is not between 200 and 399. For debugging purposes, accessing responseText
doesn’t follow this pattern and will always return the raw response. It’s recommended that you catch specific exceptions in favor of the base Exception
. Here is an example of catching an EpiFoursquareException
and falling back to the base Exception
.
NOTE: If you have set the library to operate asynchronously the exception isn’t thrown until you access any of the return values from the API call.
$fsObj = new EpiFoursquare($clientId, $clientSecret, $accessToken);
try{
$friends = $fsObj->get('/users/USER_ID/friends');
echo 'You have ' . $friends->response->friends->count . ' friends';
foreach($friends->response->friends->items as $friend) {
echo "{$friend->firstname} is your friend\n";
}
}catch(EpiFoursquareException $e){
echo 'We caught an EpiOAuthException';
echo $e->getMessage();
}catch(Exception $e){
echo 'We caught an unexpected Exception';
echo $e->getMessage();
}
-
EpiFoursquareException extends Exception
– General uncaught or unknown exceptions -
EpiFoursquareBadRequestException extends EpiFoursquareException
– 400 response code -
EpiFoursquareNotAuthorizedException extends EpiFoursquareException
– 401 response code -
EpiFoursquareForbiddenException extends EpiFoursquareException
– 403 response code -
EpiFoursquareNotFoundException extends EpiFoursquareException
– 404 response code
Foursquare-async was carefully written to maximize the efficiency of making HTTP web service requests. Knowing that curl calls are expensive, we don’t want to wait around idly while we could be doing other work. This is especially true if you need to make multiple calls on a single page. Ideally, you could fire off several requests in parallel instead of doing them one at a time. To enable asynchronous calls you will need to call useAsynchronous(true)
on the Foursquare-async object.
The key to using Foursquare-async efficiently is to delay accessing the results for as long as possible. Initiating the call fires off the HTTP request and immediately returns control back to you without blocking. The call continues to work in the background until you need the results. For the best performance it’s advised to initiate the calls as early as possible and only block by accessing the results as late as possible. The implementation details depend greatly on your framework.
$fsObj = new EpiFoursquare($clientId, $clientSecret, $accessToken);
$fsObj->useAsynchronous(true);
$venues = array('123','456','789');
$responses = array();
// send off the requests in parallel
foreach($venues as $venue) {
$responses[] = $fsObj->post('/checkins/add' array('vid' => $venue, 'broadcast' => 'public'));
}
// now we retrieve the results and ensure that each call completes
foreach($responses as $resp) {
echo "Checkin id was {$resp->response->checkin->id}\n";
}
It’s important to validate that your calls are truly asynchronous. The library includes a sequencer class which displays a graph of the calls to show you how the calls are sequenced. You can look at the file tests/sequencerTest.php
for an example.
// To display the sequence graph you can add the following code to the bottom of your page.
echo EpiCurl::getSequence()->renderAscii();
// To run the example you can execute the sequencerTest.php file from the command line
`php sequencerTest.php`
Test sequencing diagram of api calls
(http://api.foursquare.com/v2/checkins/add :: code=200, start=1283577305.2462, end=1283577305.5109, total=0.264562)
[==================================================]
(http://api.foursquare.com/v2/users/search :: code=200, start=1283577305.2726, end=1283577305.3871, total=0.114419)
[ ================= ]
(http://api.foursquare.com/v2/venues/add :: code=200, start=1283577305.2731, end=1283577305.4195, total=0.146262)
[ ============================ ]
To start off, you’ll need to create an application on Foursquare. They will give you a consumer key and a consumer secret. Copy and paste this into your site’s configuration file since you’ll be needing them later. The rest of the information is embedded in Foursquare-async.