My new application written using the Lithium PHP Framework needed to make API calls to Apple’s iTunes service. The web service in question returns JSON which can be parsed and used to build an array or object on our server via php’s native json_decode(). I couldn’t find any documentation about setting up a simple request like this but with some digging I found the lithium\net\http\Service class ready to do the job. Instead of loading up Curl or some other method, I can pull a json object down from a remote web server (or any webpage) and parse the body in less than 3 lines of code.

Looking at the lithium\net\http\Service class

	/**
	 * Initializes a new `Service` instance with the default HTTP request settings and
	 * transport- and format-handling classes.
	 *
	 * @param array $config
	 */
	public function __construct(array $config = array()) {
		$defaults = array(
			'persistent' => false,
			'scheme'     => 'http',
			'host'       => 'localhost',
			'port'       => null,
			'timeout'    => 30,
			'auth'       => null,
			'username'   => null,
			'password'   => null,
			'encoding'   => 'UTF-8',
			'socket'     => 'Context'
		);
		parent::__construct($config + $defaults);
	}

A cursory glance at the file revealed the the connection options need to be passed in via an $options config array in the class constructor. This is a lot like CakePHP’s HttpSocket class. For the purposes of an example, lets say we want to pull down all the Jack Johnson items via his artist id in iTunes. If you click http://itunes.apple.com/lookup?id=909253 you will get a nice json string representing the collection. Let’s go ahead and create a controller interface with the API.

Create app/controllers/ItunesController.php

<?php
namespace app\controllers;
use lithium\net\http\Service;

class ItunesController extends \lithium\action\Controller {

  public function get()
  {
    //instantiate the service connection
    $service = new Service(array('host' => 'itunes.apple.com'));

    //capture the response
    $data = $service->get('/lookup?id=909253');

    //decode the json
    $songs = json_decode($data);

    //now we get a nice object to work with
    var_dump(songs);

    //object(stdClass)[28]
    //  public 'resultCount' => int 1
    //  public 'results' =>
    //    array
    //      0 =>
    //        object(stdClass)[29]
    //          public 'wrapperType' => string 'artist' (length=6)
    //          public 'artistType' => string 'Artist' (length=6)
    //          public 'artistName' => string 'Jack Johnson' (length=12)
    //          public 'artistLinkUrl' => string 'http://itunes.apple.com/us/artist/jack-johnson/id909253?uo=4' (length=60)
    //          public 'artistId' => int 909253
    //          public 'amgArtistId' => int 468749
    //          public 'amgVideoArtistId' => null
    //          public 'primaryGenreName' => string 'Rock' (length=4)
    //          public 'primaryGenreId' => int 21
    }
}

?>

Dont forget to include the namespace to include the Service library at the top of your controller. You can of course play with the constructor options to work with nearly any web url. Best of all this doesn’t need CURL to be installed with your php since it relies upon php native streams functions. This is some really awesome stuff and I must say that I am finding it trivially easy to implement a web service using Lithium. I could easily dump the iTunes objects into MongoDB for later retrieval with very little conversion.

As always please share your thoughts in the comments.

Tagged with:
 
  • http://twitter.com/justinjenkins Justin Jenkins

    That’s a nice snippet, should that get() be in the Controller, or in the Model tho?

    • Anonymous

      Well it’s in the controller for the sake of a simple example. You can always put it into a Model if you sharing these calls in your app. This is one of those questions that really depends upon how your app is structured. Keep in mind that if you are taking user input, you still have to touch the controller at some point to handle the request and you can always extract your logic into the model if you find out it should really be there.

Set your Twitter account name in your settings to use the TwitterBar Section.