Friday, 31 October 2008

Tinyizing URLs with Zend_Http_Client

While doing some initial research for a blog related automation task to implement I learned some more about services which transform long URLs into short ones. The well-knownst of these services, due to the Twitter hype, is probably TinyURL which can be accessed via a classic webinterface or by calling a public API. In a recent blog post Dave Marshall outlined a quick workaround for tweeting via the Zend_Http_Client component which is a reasonable approach for calling services that aren't in the Zend Framework core yet like Zend_Service_Twitter or are not supported out of the box. Therefore this post will try to describe a Zend Framework way of creating tinyized URLs.

Getting tiny tiny y'all

According to Wikipedia there are numerous services available e.g. RubyUrl providing the same feature as TinyURL, so to be prepared for the future and thereby maybe violating the YAGNI principle I decided to declare a very basic interface first in case of switching the service provider someday.
<?php
/**
* 'Interface-level' PHPDoc Block
*/
interface Recordshelf_Service_UrlShortener_Interface
{
public function __construct($serviceEndpoint = '');
public function shortenize($url);
}
The next code snippet shows the implementation for the TinyURL service programmed against the interface and hosting an additional alias method called tinyize which is simply wrapping the actual worker method. The service utilizes Zend_Http_Client by setting the endpoint of the service, transmitting a GET request parameterized with the URL to shorten against it and returning the response containing the tinyized URL.
<?php
require_once('Zend/Http/Client.php');
require_once('Recordshelf/Service/UrlShortener/Interface.php');
/**
* 'Class-level' PHPDoc Block
*/
class Recordshelf_Service_TinyUrl implements
Recordshelf_Service_UrlShortener_Interface
{
/**
* The service endpoint
*
* @var string
*/
private $_serviceEndpoint = null;
/**
* Recordshelf service tinyURL constructor
*
* @param string $serviceEndpoint
*/
public function __construct(
$serviceEndpoint = 'http://tinyurl.com/api-create.php')
{
$this->_serviceEndpoint = $serviceEndpoint;
}
/**
* Shortenizes a given Url
*
* @param string $url
* @return string
* @throws Exception
*/
public function shortenize($url) {
if (is_null($this->_serviceEndpoint)) {
throw new Exception('No service endpoint set');
}
$client = new Zend_Http_Client($this->_serviceEndpoint);
$client->setParameterGet('url', $url)
->setMethod(Zend_Http_Client::GET);
try {
$response = $client->request();
} catch (Exception $e) {
throw $e;
}

if (200 === $response->getStatus()) {
return $response->getBody();
} else {
throw new Exception($response->getStatus() . ": " .
$response->getMessage());
}
}
/**
* Alias method for the shortenize method
*
* @param string $url
* @throws Exception
* @see shortenize
*/
public function tinyize($url)
{
return $this->shortenize($url);
}
}
Now with everything hopefully operating smoothly it's time for a test-drive, yeah I'm lazy and cut that development approach called TDD, by creating a service instance and requesting a TinyURL for the Zend Framework website as shown in the outro listing.
<?php
$service = new Recordshelf_Service_TinyUrl();
$service->tinyize('http://framework.zend.com');
// => http://tinyurl.com/nf8kf
In case off considering or favouring a more framework independent approach there are also other blends available like one via file_get_contents or via curl. Happy tinyizing!

6 comments:

Wil Sinclair said...

Have you seen this proposal yet? http://framework.zend.com/wiki/display/ZFPROP/Zend_Service_ShortenUrl+-+Martin+Hujer

You could definitely help out here if inclined:

* Help Martin by reviewing the proposal. Maybe even co-author it with him if you feel significant work needs to be done.

* Contribute Zend_Service_TinyUrl. No promises, but that would be a pretty solid candidate for the standard library.

,Wil

Raphael Stolt said...

Hi Wil,

Thanks for embarrassing me ;D. No haven't seen that proposal yet. Guess I got all excited about the topic and went sloppy on the research part.

Will definitely have a look at it.

Raphael

Anonymous said...

shortenize() looks silly, why not just use shorten()

Raphael Stolt said...

You are right shorten() might be a preferable name as it is also used in the Zend_Service_ShortenUrl proposal.

phpimpact said...

A working prototype, nice ;)

Thanks Raphael

Dave Marshall said...

Like it Raphael, I have similar code just above the twitter part in my application!