Guzzle is a PHP framework for building REST webservice clients. Guzzle provides the tools necessary to quickly build a testable webservice client with complete control over preparing HTTP requests and processing HTTP responses::
Most web service clients follow a specific pattern: create a client class, create methods for each action that can be taken on the API, create a cURL handle to transfer an HTTP request to the client, parse the response, implement error handling, and return the result. You've probably had to interact with an API that either doesn't have a PHP client or the currently available PHP clients are not up to an acceptable level of quality. When facing these types of situations, you probably find yourself writing a webservice that lacks most of the advanced features mentioned by Michael. It wouldn't make sense to spend all that time writing those features-- it's just a simple webservice client for just one API... But then you build another client... and another. Suddenly you find yourself with several web service clients to maintain, each client a God class, each reeking of code duplication and lacking most, if not all, of the aforementioned features. Enter Guzzle.
Guzzle is used in production at `SHOEBACCA.com <http://www.shoebacca.com/>`_, a mutli-million dollar e-commerce company. Guzzle has 100% code coverage; every line of Guzzle has been tested using PHPUnit.
The Guzzle ``Guzzle\Service\Client`` object can be used directly with a simple web service. Robust web service clients should interact with a web service using command objects, but if you want to quickly interact with a web service, you can create a client and build your HTTP requests manually. When creating a simple client, pass the base URL of the web service to the client's constructor. In the following example, we are interacting with the Unfuddle API and issuing a GET request to retrieve a listing of tickets in the 123 project::
<?php
use Guzzle\Service\Client;
$client = new Client('https://mydomain.unfuddle.com/api/v1');
Notice that the URI provided to the client's ``get`` method is relative. The path in the URI is also relative. Relative paths will add to the path of the base URL of the client-- so in the example above, the path of the base URL is ``/api/v1``, the relative path is ``projects/123/tickets``, and the URL will ultimately become ``https://mydomain.unfuddle.com/api/v1/projects/123/tickets``. If a relative path and a query string are provided, then the relative path will be appended to the base URL path, and the query string provided will be merged into the query string of the base URL. If an absolute path is provided (e.g. /path/to/something), then the path specified in the base URL of the client will be replaced with the absolute path, and the query string provided will replace the query string of the base URL. If an absolute URL is provided (e.g. ``http://www.test.com/path``), then the request will completely use the absolute URL as-is without merging in any of the URL parts specified in the base URL.
Templates can be specified in the client's get, head, delete, post, and put methods, which allow placeholders to be specified in the the request template that will be overwritten with an array of configuration data referenced by key.
All requests in the above client would need the basic HTTP authorization added after they are created. You can automate this and add the authorization header to all requests generated by the client by adding a custom event to the client's event manager. Another annoyance you can solve with Guzzle's event system is automatically creating SimpleXMLElement objects for a response when the content type is ``application/xml``. Here's an example of creating a very simple Unfuddle client that lists the email addresses of everyone in your project (note: Guzzle has a robust Unfuddle client-- this is just an example)::
<?php
$client = new Client('https://mydomain.unfuddle.com/api/v1');
You will need to add Guzzle to your application's autoloader. Guzzle ships with a few select classes from other vendors, one of which is the Symfony2 universal class loader. If your application does not already use an autoloader, you can use the autoloader distributed with Guzzle::
Guzzle services are distributed separately from the Guzzle framework. Guzzle officially supports a few webservice clients (these clients are currently what we use at SHOEBACCA.com), and hopefully there will be third-party created services coming soon:
When installing a Guzzle service, check the service's installation instructions for specific examples on how to install the service. Most services can be installed using a git submodule or, if available, a PEAR package through pearhub.org::
Services that are installed within the path to Guzzle under the Service folder will be autoloaded automatically using the autoloader settings configured for the Guzzle library (e.g. /Guzzle/Service/Aws). If you install a Guzzle service outside of this directory structure, you will need to add the service to the autoloader.
Create a services.xml that your ServiceBuilder will use to create service clients. The services.xml file defines the clients you will be using and the arguments that will be passed into the client when it is constructed. Each client + arguments combination is given a name and referenced by name when retrieving a client from the ServiceBuilder.::
// You can get access to the HTTP request issued by the command and the response
echo $command->getRequest();
echo $command->getResponse();
The ListBucket command above returns a BucketIterator which will iterate over the entire contents of a bucket. As you can see, commands can be as simple or complex as you want.
If the above code samples seem a little verbose to you, you can take some shortcuts in your code by leveraging the Guzzle command factory inherent to each client::
The code sample above wraps a ``Zend_Log`` object using a ``Guzzle\Common\Log\ZendLogAdapter``. After attaching the request to the plugin, all data sent over the wire will be logged to stdout. The above code sample would output something like::
* Connection #1 to host www.google.com left intact
<!doctype html><html><head>
[...snipped]
PHP-based caching forward proxy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Guzzle can leverage HTTP's caching specifications using the ``Guzzle\Http\Plugin\CachePlugin``. The CachePlugin provides a private transparent proxy cache that caches HTTP responses. The caching logic, based on `RFC 2616 <http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html>`_, uses HTTP headers to control caching behavior, cache lifetime, and supports ETag and Last-Modified based revalidation::
<?php
use Doctrine\Common\Cache\ArrayCache;
use Guzzle\Common\Cache\DoctrineCacheAdapter;
use Guzzle\Http\Plugin\CachePlugin;
use Guzzle\Http\Message\RequestFactory;
$adapter = new DoctrineCacheAdapter(new ArrayCache());
// The next request will revalidate against the origin server to see if it
// has been modified. If a 304 response is recieved the response will be
// served from cache
$request->setState('new')->$request->send();
Guzzle doesn't try to reinvent the wheel when it comes to caching or logging. Plenty of other frameworks, namely the `Zend Framework <http://framework.zend.com/>`_, have excellent solutions in place that you are probably already using in your applications. Guzzle uses adapters for caching and logging. Guzzle currently supports log adapters for the Zend Framework and cache adapters for `Doctrine 2.0 <http://www.doctrine-project.org/>`_ and the Zend Framework.