Make the Facebook PHP SDK v4 better with Guzzle 4 HTTP client

Using Guzzle 4 HTTP client with Facebook PHP SDK v4

Jun 17, 2014

The Facebook PHP SDK v4 launched publicly back on April 30th, 2014 with a bit of a buggy implementation of a cURL HTTP client. And what's worse, it was so tightly coupled to the FacebookRequest class that it was impossible to overwrite.

In fact, it was one of the very first issues submitted on GitHub. And after some back and forth on the refactor, injectable HTTP clients was born. And it gets better! Stream wrapper & Guzzle HTTP client implementations were added!

If you're having trouble getting the SDK to work on your server due to cURL or stream wrapper issues, you definitely want to implement Guzzle 4 for the SDK.

The default HTTP client setup

Out of the box, the SDK will try to use the cURL HTTP client implementation. If cURL is not detected, it will automatically fall back to the stream wrapper implementation and try to make calls to Graph using stream_context_create() and file_get_contents().

The main problem is that both HTTP client implementations are custom-coded for the SDK. Which means there are bugs that keep popping up.

My intuition tells me that there will be many more bugs found in the cURL and stream wrapper implementations going forward.

Overwriting the default HTTP client

But we can inject our own custom HTTP client! You can write your own implementation using whatever super-awesome HTTP client package you like to use. All you have to do is code your implementation to the interface \Facebook\HttpClients\FacebookHttpable found here.

For example, your custom implementation might look like this (with real code instead of comments obviously.)

use Facebook\HttpClients\FacebookHttpable;

class MyCustomHttpClientForFacebook implements FacebookHttpable {

  public function addRequestHeader($key, $value) {
    // Add the headers we want to send with the request
  }

  public function getResponseHeaders() {
    // Return the headers returned in the response
  }

  public function getResponseHttpStatusCode() {
    // Return the HTTP status response code
  }

  public function send($url, $method = 'GET', $params = []) {
    // Sends a request to the server
  }

}

To inject that into the SDK, add this line before you send any requests to Graph with FacebookRequest:

use Facebook\FacebookRequest;

FacebookRequest::setHttpClientHandler(
  new MyCustomHttpClientForFacebook()
  );

And BOOM! All the requests the SDK makes to Graph will be done via your custom HTTP client implementation.

Implementing Guzzle

So how do we write a custom implementation for Guzzle 4? We don't! It's already included in the SDK but it's not enabled by default. So we just have to enable it.

First make sure you have Guzzle 4 installed with composer.

{
    "require": {
        "guzzlehttp/guzzle": "~4.0"
    }
}

Then tell the SDK that you want to use the Guzzle implementation.

use Facebook\FacebookRequest;
use Facebook\HttpClients\FacebookGuzzleHttpClient;

FacebookRequest::setHttpClientHandler(
  new FacebookGuzzleHttpClient()
  );

And BOOM! All your requests will be handled by the far-less-buggy HTTP client we all know and love, Guzzle.

If you found this guide helpful, say, "Hi" on twitter! I'd love to hear from you. :)