HomeAJAX & Prototype Google's Closure Compiler Service API: Talking to the API via a PHP Class
Google's Closure Compiler Service API: Talking to the API via a PHP Class
In this second part of the series, I develop a concrete PHP class derived from the abstract parent defined in the previous tutorial. This new class implements some refined methods that permit you to interact “face-to-face” with Google's Closure Compiler Service API in a pretty straightforward fashion.
If the ever-increasing size of your custom JavaScript files has you desperately looking for an application that lets you optimize them through a few simple options, then you should take a close look at Google's Closure Compiler Service API. This web service released recently by the search company (at least at the time of this writing) will permit you to perform the entire optimization process either manually by using a graphical user interface, or programmatically via POST HTTP requests.
If you've read the introductory tutorial of this series, you're familiar in general terms with the capabilities that the Closure Compiler API offers. In that part I gave a brief overview of the API’s main features, including the ability to specify the level of optimization that will be applied to the target files, and the format (text, XML or JSON) in which the files will be dispatched to the client.
It’s valid to recall that the main objective of this series is to demonstrate, in a step-by-step manner, how to interact with the Closure Compiler Service API using PHP. This process can be ported to other programming languages with minor efforts. In keeping with that premise, in the previous article I went through the development of an abstract PHP class, which encapsulated most of the functionality required to perform HTTP requests to a given host and a TCP port via a set of simple methods.
With that abstract parent already defined, the next step is to create a concrete subclass that is capable of talking directly to the Closure Compiler Service API. This subclass will allow us to automatically optimize multiple JavaScript files easily, without the need to explicitly use the compiler’s GUI.
With that said, it’s time to start building the aforementioned concrete PHP class. Want to see how this will be done? Just keep reading.
Creating the backend to interact with the Closure Compiler Service API: creating an abstract HTTP request handler class in PHP
As I just explained, my goal here is simply to show how to consume Google’s Closure Compiler Service API using an object-oriented backend composed of a few sample PHP classes. To accomplish this, I first developed an abstract class, which was nothing but an enhanced wrapper of the “fsockopen()” PHP function. The full source code of the class looked like this:
// constructor public function __construct(array $data, array $settings = array()) { $this->setData($data); if (array_key_exists('url', $settings)) { $this->setUrl($settings['url']); } if (array_key_exists('port', $settings)) { $this->setPort($settings['port']); } if (array_key_exists('method', $settings)) { $this->setMethod($settings['method']); } }
// set the data that will be passed with the request public function setData(array $data) { if (empty($data)) { throw new HttpRequestHandlerException('The request arguments are not valid.'); } $this->_data = $data; return $this; }
// get the specified request data public function getData() { return $this->_data; }
// set the URL the request will be made to (implemented by subclasses) abstract public function setUrl($url);
// get the given URL public function getUrl() { return $this->_url; }
// set the TCP port the request will be made on (implemented by subclasses) abstract public function setPort($port);
// get the given port public function getPort() { return $this->_port; }
// set the request method (GET or POST) public function setMethod($method = 'GET') { $method = strtoupper($method); if (!in_array($method, array('GET', 'POST'), TRUE)) { throw new HttpRequestHandlerException('The request method is not valid.'); } $this->_method = $method; return $this; }
// get the request method public function getMethod() { return $this->_method; }
// add a new request header public function addHeader($key, $header) { $key = strtolower($key); if (!array_key_exists($key, $this->_headers)) { $this->_headers[$key] = $header; } return $this; }
// remove a specified request header public function removeHeader($key) { $key = strtolower($key); if (array_key_exists($key, $this->_headers)) { unset($this->_headers[$key]); } return $this; }
// get a specified request header public function getHeader($key) { $key = strtolower($key); if (array_key_exists($key, $this->_headers)) { return $this->_headers[$key]; } }
// get the header included in the response public function getResponseHeader() { return $this->_responseHeader; }
// get the content included in the response public function getReponseContent() { return $this->_responseContent; }
// send an HTTP request to the specified URL and TCP port public function sendRequest() { // parse and urlencode the request data $data = ''; foreach ($this->_data as $key => $value) { $data .= '&' . $key . '=' . urlencode($value); } $data = trim($data, '&'); // parse the given URL $url = parse_url($this->_url); if (!isset($url['host']) OR !isset($url['path'])) { throw new HttpRequestHandlerException('No host or path was specified.'); } $host = $url['host']; $path = $url['path']; // open a socket connection on the specified TCP port if (!$fp = fsockopen($host, $this->_port)) { throw new HttpRequestHandlerException('Error opening socket connection to the URL '. $this->_url . ' on port.' . $this->_port); } fputs($fp, "$this->_method $path HTTP/1.0rn"); fputs($fp, "Host: $hostrn"); fputs($fp, "Content-type: application/x-www-form-urlencodedrn"); fputs($fp, "Content-length: ". strlen($data) . "rn"); fputs($fp, "Connection: closernrn"); fputs($fp, $data); // get the response of the request $response = ''; while(!feof($fp)) { $response .= fgets($fp, 128); } // close the socket connection: fclose($fp); // process the response $response = explode("rnrn", $response, 2); $this->_responseHeader = $response[0]; $this->_responseContent = $response[1]; return $this->_responseContent; }
// send the specified header public function sendHeader($key) { if ($header = $this->getHeader($key)) { header($header); } } }
(HttpRequestHandlerException.php)
<?php
class HttpRequestHandlerException extends Exception{}
If you haven't worked with sockets in PHP before, don’t worry; the previous class handles the process transparently behind the scenes through its “sendRequest()” method. Besides, the class implements some getters and mutator methods that allow you, among other things, to set the URL and TCP port on which HTTP requests will be made, which are pretty easy to grasp.
So far, so good. Having defined an abstract parent that triggers HTTP requests to a specific URL on a TCP port, we now need to start building the concrete class responsible for communicating directly with the Closure Compiler Service API. As you’ll see in a moment, the driving logic of this class will be very easy to understand, but to learn how it’ll be created you’ll have to click on the following link and keep reading.