Archive for October, 2009

A Galaxy Phar, Phar Away

One of the new features of PHP 5.3 that hasn’t got a whole lot of attention is the inclusion of the Phar extension in the main distribution. Phar files are to PHP what Jar files are to Java. Basically they allow you to package up php into a single archive.

What many of you may not know is that the Phar file format has actually been around for quite some time.  It started out as a PEAR package called PHP_Archive and was re-implemented as a PECL extension some time ago and works with PHP versions earlier than 5.3. You just need to install it with PECL.

There have been a number of articles explaining how you can package up entire application into a Phar file and run you site from it.  This is a great idea but does not seem to have attracted much attention.  What I have been looking at recently does go quite that far. Instead of packaging entire application in a Phar file, I have been looking at treating phar files like libraries, or shared objects.

The Phar file format also allows you to specify a stub. The stub is run automatically when the phar file is included in your php script.

This actually gives you a really powerful mechanism for creating libraries.  All you code can sit in the library and any setup needed can be performed by the stub.

As part of my development of the Morph library I have been working on that provides a simple way to use MongoDB with PHP I have a process that builds a phar file of the library.  Morph is designed to work best with an autoloader that translates class names into file paths. To make it super easy I have put together a stub file for the archive that provides and registers the autoloader.

The autoloader is actually dead easy:

class MorphAutoloader {
   private static $classes = array(
      'ClassName' => 'phar://path/within/phar/ClassName.php'
   );
   public static function load($className) {
      $isLoaded = false;
      if (isset(self::$classes[$className])) {
         include self::$classes[$className];
         $isLoaded = true;
      }
      return $isLoaded;
   }
}
spl_autoload_register(array('MorphAutoloader', 'load'));
__HALT_COMPILER();

The Phar::mapPhar() function call at the begining tell php ‘Hey, your in a phar file’, PHP will then go away and read the manifest of the Phar file so it knows what is in it.  I use of spl_autoload_register() rather than just defining a function call __autoload as it actually allow the registering of multiple autoloaders. This means that the library autoloader does not interfere with any defined in the application itself.

Finally, the call to __HALT_COMPILER() is a requirement of the Phar file stub and should appear as the very last line of your stub file.

Then all you project needs to do is include the Phar file. Everything else is a taken care of by the phar file itself. Think how much easier managing upgrades becomes when all you have to do is replace one file.

—-

Moose