Easy Package Management With Composer

Easy Package Management With Composer

Tutorial Details
  • Topic: PHP, Package management
  • Difficulty: Medium
  • Estimated Completion Time: 1 hour

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.

Installing the application on anything Unix flavoured is easy:

$ cd /path/to/my/project
$ curl -s http://getcomposer.org/installer | php

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:

{
    "require": {
        "kriswallsmith/assetic": "1.0.*"
    },
    "config" : {
        "vendor-dir" : "packages"
    }
}

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:

\<Vendor Name>\(<Namespace>\)*<Class Name>

Another example might be the Buzz HTTP package, which looks like so:

$browser = new Buzz\Browser;
$response = $browser->get('http://www.google.com');

echo $browser->getLastRequest()."\n";   
echo $response;

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.

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://wouterj.nl Wouter J

    I’m using Composer with Symfony2.1 and I like the idea and the program.

    For windows users there is another option to download Composer:
    php -r “eval(‘?>’.file_get_contents(‘http://getcomposer.org/installer’));”

    Just a sidenote: You need to have GIT installed and GIT needs to be in the environement variables of your system.

  • http://github.com/joseym Josey Morton

    A great “mass installer” has recently surfaced which opens support for composer packages to major frameworks/codebases like cakephp, fuelphp, lithium, zend, joomla, wordpress and a ton of others in one go.

    Really cool project: https://github.com/composer/installers

  • James fuller

    Overall a nice overview, however I take issue with your closing remarks. How is composer a replacement for PECL? Does composer magically install and compile php extensions as well?

    • http://philsturgeon.co.uk Phil Sturgeon
      Author

      It’s a replacement for the functionality of that. So if you want the HTTP PECL you need to install PEAR, set up a compiler, enable the extensions .so or .dll, etc just to get it working. With Composer you’re using on-the-fly PHP but it’s dropin, so your dependency has been handled in one location along with everything else.

      You can replace several PECL packages with items from Packagist, for example a YAML parser:

      PECL: http://pecl.php.net/package/yaml
      Composer: http://packagist.org/packages/symfony/yaml

      Now of course people will say “sure but PECLs are compiled so they run faster” and im going to say “Yep” but that is not what we’re talking about here.

      • http://twitter.com/sizl kevvy

        “run faster” as in time it takes to install the extension or the library performing in runtime?

  • John

    I knew Composer was out there, but never made the time to dive into it. Thanks for putting together this intro!

    Are there any packages that you would recommend out of the gate?

    • http://philsturgeon.co.uk Phil Sturgeon
      Author

      One I would recommend is https://github.com/fuelphp/validation. FuelPHP 2.0 is going to be composed (ha) of lots of these sorts of packages, so anyone can start using various components as soon as they are released.

      I’ll be porting my NinjAuth and OAuth 1 & 2 packages too as soon as I can find the time, as they are Fuel only right now.

      Assetic
      Buzz
      https://github.com/fuelphp/util
      Symfony\Yaml

      There are more, and there will be a LOT more soon. People are starting to realise that building out the same code for every single framework is a waste of time. Another fun thing is that people are starting to unit test these packages too, meaning the quality of PHP code is going up.

  • http://atomphp.com/ Chase

    @james I don’t think he was saying composer is a replacement for PECL, so much as it allows you to use alternatives without requiring your user base to install extensions.

    A great example, is something like PHPSecLib, where you can utilize PECL functionality when available, or fallback to composer-installed libraries when not.

  • http://www.jaaprood.com JaapRood

    Great article Phil! Composer is the way forward in my view.

    For everyone who is on Mac OSX and used homebrew, you can easily install Composer as follows (straight from the Composer Github repo):

    1. Tap the homebrew-php repository into your brew installation if you haven’t done yet: brew tap josegonzalez/homebrew-php
    2. Run brew install josegonzalez/php/composer.
    3. Use Composer with the composer command.

  • Dragos

    Take for example https://github.com/fuelphp/util, is it possible to install this within code igniter as a composer package (I haven’t found a package yet, do you know if it’s going to be added as one?)
    And if so, do you have a usage example?

    Or even better, https://github.com/fuelphp/cache – once installed within CI, how would you use it?
    Is it possible to be auto-loaded for the entire app?

    Thanks Phil, we really appreciate your work!

  • kenneth

    who is going to do this for windows .. i seem not to hack it…………………..

    • http://diywebdev.com/ DIYWebDev

      Hi, doing this in windows is even easier, there is an installer for composer, here is an article on setting up composer in windows. Going to save you much time :)

    • http://twitter.com/eckert_ryan1 Eckert Ryan

      :( it supports windows out of the box… but why on windows? No serious PHP app is hosted on Windows…ever….

  • John M

    why do you use “use” in your PHP code? You can AssetCollection without it because you have already autoloaded the classes?

    • http://hg.longo.me/ Flatline

      Not exactly. The “use” statement is used to import a class to the current namespace, so if weren’t used instantiating the AssetCollection class would have to be done like so:

      $js = new AsseticAssetAssetCollection(array(
      new AsseticAssetGlobAsset(‘/path/to/js/*’),
      new AsseticAssetFileAsset(‘/path/to/another.js’),
      ));

      • http://www.facebook.com/people/Long-Jiang/100000741339775 Long Jiang

        this is ugly

  • Casey

    Thanks for the article.

    I use Git to deploy to my server, and in most cases the vendor directory is not tracked by the repository. So, it is not affected by deployment. What is the best workflow to keep the server in sync? As Phil mentioned in Real World part, should I also install composer to the server? If so, isn’t it risky to run composer update/install on a production server?