Easy Package Management With Composer

Let's face it: PHP has had a rocky history with package management, and as a result, it is pretty rare to find a developer who actively uses systems like PEAR. Instead, most developers have chosen their favorite framework, which has code specifically written for it to handle various things, like DB interaction, ORM's, OAuth, Amazon S3 integration, etc.

The downside here, though, is that switching frameworks (or returning to not using a framework at all) can be a nightmare, as it involves relearning everything to use brand new tools - and that is no easy task. Well, Composer can fix that!

Introduction

"The glue between all projects."

Composer sets out to solve this situation by positioning itself as "the glue between all projects" - meaning that packages can be written, developed and shared in a format that other developers can plug into other applications with ease.

This article sets out to show you how to install and work with Composer packages. By the end of this article, you will be able to plug and play with chunks of code in any framework, whether you work with CodeIgniter, FuelPHP, Laravel, Symfony2, Lithium, Yii, Zend... or anything else.

Step 1 - Installing Composer

Composer has two main logical parts: there is a repository that stores packages, and then there's the command-line application, which helps you find, download, update and share code.

It's as easy as that! You'll now have a composer.phar file listed in your project, which contains all of the logic for the command line utility.

You can confirm that it has been installed by running:

$ php composer.phar

This command will reveal all available commands.

A personal preference of mine is to run an extra command:

$ sudo mv composer.phar /usr/bin/composer

This moves the file into your bin, which allows you to access all commands with the much shorter example:

$ composer about

If you're running Windows, you can just download this file, and run it through the PHP interpreter - wherever that may be installed.

Step 2 - Understanding composer.json

If you are a Ruby developer, you'll likely be familiar with the Gemfile. Or, Node developers will know about package.json. Similarly, Composer uses a composer.json file to specify settings and package requirements for your application.

In its most basic form, the composer file will look like this:

{
"require": {
"kriswallsmith/assetic": "*"
}
}

This will require the "Assetic" package, created by "kriswallsmith", and will require any version. To specify a specific version, you could instead use:

"kriswallsmith/assetic": "1.0.3"

You can even combine the two approaches, like so:

"kriswallsmith/assetic": "1.0.*"

This will allow any minor update to automatically be included, but it not upgrade to 1.1.0, as that might have some interface changes a developer will need to watch out for.

Step 3 - Installation Requirements

Now that you have one or more packages listed within your composer.json, you can run:

$ php composer.phar install

...Or, if you've used my trick to shorten it on Unix machines (see above):

$ composer install

You'll now notice files being downloaded and placed into a new vendors/ folder within the root of your application. This logic can be changed, using the following configuration option:

Step 4 - Autoloading

Autoloading in PHP has been a bit of a mess for some time.

Autoloading in PHP has been a bit of a mess for some time, as every developer has his or her own ways of handling things. Some packages, like Smarty, use their own autoloading, some developers place multiple classes into one file or have lower-case file names - it's all very random.

PSR-0 is a standard, created by the PHP Standards Group, to calm this mess down; Composer will work with it by default. Composer bundles with a PSR-0 autoloader, which you can include in your project with only a single line:

include_once './vendor/autoload.php';

Obviously, if you changed the vendor directory, you'll need to update that.

You can now use the code in your applications:

<?php
use Assetic\Asset\AssetCollection;
use Assetic\Asset\FileAsset;
use Assetic\Asset\GlobAsset;
$js = new AssetCollection(array(
new GlobAsset('/path/to/js/*'),
new FileAsset('/path/to/another.js'),
));
// the code is merged when the asset is dumped
echo $js->dump();

This is an example of Assetic in use. Yes, there is a lot of namespace code in there, but this is done to avoid conflicts between packages. The naming convention for PSR-0 is essentially:

That might look like a glorified file_get_contents(), but it handles all sorts of smart logic in the background for working with HTTP Response/Request - and you can see the namespace syntax is a little less intense.

Step 5 - Real World

If you want to be really clever, you can automate the whole process.

Currently, most projects store all PHP dependencies in the main code repository; so, if you are using the Facebook SDK, for example, you just shove that version into your code by copy-pasting the code from GitHub or extracing a ZIP file. Then, you add it to your versioning system and push the changes.

That version then sits with your code as a static file, which, at some point, you may or may not remember to upgrade - IF you notice that Facebook have released an updated version. The new version of the file goes over the top and you push those new changes, too.

You can use Composer to avoid needing to pay attention to the versions, and just run an update, and commit all the changes. But why have loads of code in your repository that you don't need to have in there?

The neatest solution is to add vendors/ to your "Ignore" list (E.g: .gitignore) and keep your code out of there entirely. When you deploy code to your hosts, you can just run composer install or composer update.

If you want to be really clever, you can automate the whole process, so if you have hosting in the cloud, you can set up hooks to run composer install as soon as your new code is pushed!

Summary

You'll start to see a lot more of Composer going forward, as various PHP frameworks have begun providing various levels of integration; FuelPHP will be built as Composer packages, CodeIgniter will support autoloading, and Symfony2 is already using it extensively.

Composer is a great way to add dependencies to your projects without needing to install PECL extensions or copy and paste a bunch of files. That way of doing things is extremely outdated, and requires too much of a developer's time.