Fast Plist Creation in PHP

When we originally designed the BeerMap API we decided to provide the data in a plist format, along with json and XML.

The plist format isn’t widely used for APIs, however iOS provides efficient inbuilt parsing of this file type and we also found this to be much easier to implement in terms of code complexity.

For example, you can just do this:

NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:@"http://www.example.com/data.plist"]];

For the past two years we’ve used the CFPropertyList library which in my opinion is the best and most functional library for reading and writing plist files in PHP.

If you find issues, please post on Github, or even better, fork and create a pull request!

However, in BeerMap we just need to create and output plists as fast as we can without any need to read or represent them in an object format. Looking at the xdebug output for the BeerMap API it became evident that the plist creation was by far the biggest bottleneck, mostly because of the XML object representation.

So, in summary I’ve created a quick class which just generates an XML string from an associative array instead of using XML objects. From my testing using ab, I was getting almost twice the number of request per second.

You can find the code at Github – https://github.com/paulbain/Bain-PHP-Library where I’ve started a library in the Zend Framework layout.

Here’s an example of how to use it:

require_once 'Plist.php';
 
//Get some data in an associative array
$data = array(
	'reviews'=>; array(
        array('title'=>;'My Review','comment'=>;'It\'s awesome','rating'=>;5)
    )
);
// Specifiy types for any non-string named keys
$types = array(
    'rating'=>;'real'
);
 
//Create the Plist
$plist = new Bain_Plist($data,null,$types);
 
//Output the plist! (Maybe you'll need an XML header)
echo $plist;

If you’re using the Zend Framework auto loader, just place the library in your path and register the namespace:

$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->;registerNamespace('Bain_');

If you use this in a project leave a comment!

Speeding up CURL Requests in PHP

Recently I’ve been working with an extremely data intensive flight API which takes several seconds to process a response and up to 60 seconds to transfer the data.

Unfortunately there is no way to reduce the amount of content in the response which would have been the best optimisation. A good hint in cases like these is to try to get the server to compress the content. Using one simple CURL option I was able to speed up each request by around 40 seconds, extremely satisfying!

curl_setopt($curl,CURLOPT_ENCODING,'gzip');

If you’re actually creating the API using PHP, you may want to look at tweaking your php.ini settings to make sure zlib output compression is enabled.
You can also play with the output compression level, with 1 being the lowest and 9 the highest. Be careful however as a higher level of compression may result in high server load.

zlib.output_compression = On
zlib.output_compression_level = 6

EasyTube Plugin Updated

I’ve just released an update to EasyTube which is my most popular WordPress plugin that allows people to embed YouTube videos in posts and pages using a single tag.

Version 1.7 update includes:

  • Multiple bug fixes including a major problem with video sizes
  • Addition of new widescreen video formats
  • Updated embed to include the fullscreen option

For more information visit the WordPress.org.

Snow Leopard, Zend Framework and MySQLi Problem

I spent a good hour banging my head against the desk this evening trying to work out why Zend Framework row objects have stopped working after upgrading to Snow Leopard and installing the new iPhone SDK.

I traced all the way though to the Zend_Db_Statement_Mysqli class which giving the following error:

Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be a reference, value given in Zend/Db/Statement/Mysqli.php on line 205

I was half way installing the macports PHP package when I thought I should probably try a different adapter which worked! So if you’re having difficulties, try the PDO_MYSQL driver instead.

Inserting Default Content into the WordPress Visual Editor

I’ve been working on a WordPress layout which needs two columns of user editable content per page. There are many ways you could do this with WordPress, however to make it as easy as possible for the content editors I though it would be easier if the visual editor had some default layout information inserted when creating a post.

I knew there must be an easy way to do this using the action API in WordPress and I came across this article by WPRecipies which suggests putting the following code in the functions.php of your theme:

add_filter( 'default_content', 'my_editor_content' );
function my_editor_content( $content ) {
$content = "If you enjoyed this post, make sure to subscribe to my rss feed.";
return $content;
}

I inserted a couple of divs for the columns into mine so I also wanted to add some basic styling to the editor. I know this probably isn’t the best way and I’m sure someone will correct me, but I just added the style to the end of the TinyMCE stylesheet which can be found here in /wp-includes/js/tinymce/themes/advanced/skins/wp_theme/content.css

EDIT: you can do this for custom post types too, just change the “myposttype” to be set to your type:

add_filter( 'default_content', 'my_editor_content' );
function my_editor_content( $content) {
    global $post_type;
    if($post_type=='myposttype'){
        $content .= "If you enjoyed this post, make sure to subscribe to my rss feed.";
    }
    return $content;
}

Finding Your Way with an iPhone and PHP

The iPhone has undoubtedly revolutionised mobile phone technology, providing users access to vast amounts information wherever they are and more importantly information about where they are.

One of the projects I have been working is BeerMap, a location aware iPhone application which shows you nearby pubs, how people have rated beer and lets your add to the database by uploading reviews and images.

My role in this project was to produce the web service to manage all of the information, and I thought it may be useful to give a summary of the technologies used.

PHP & The Zend Framework

The Zend Framework is an extensive PHP library providing the MVC approach to code structure which is also recommended for iPhone development.

I also heavily extended the Zend_Controller_Action class to incorporate authentication and context switching depending on the response type needed.

MySQL Stored Procedures

All our data is stored in a MySQL database, so it was logical to also create a mechanism within the database to calculate distances depending on longitude and latitude. This calculation can be relatively expensive so I am looking a ways to further optimise this process, however it appears to be working relatively efficiently at the moment.

Plists

Web services generally will provide a response in XML or JSON, however using these response formats would require additional libraries to be included within the iPhone app, increasing its size and complexity. However, by generating a Plist response, the iPhone can read this without any complex parsing or processing.

For this we modified a version of the CFPropertyList library and added a better mechanism for guessing variable types which I hope will be integrated into the original library at some point soon.

Further Information

Above is just a very brief summary of the technologies used, however please contact me for more information and take a look at the websites below:

Photo Credit: Will Ockenden