One of the most recurring events I face in the projects I'm involved is “How the hell do I manage all the dependencies?” You have internal libraries, frameworks, external libraries, it is just a big mess.

It is very hard to ensure all developers are using the same version of a specific library.

Sometimes their distribution provides a newer version and they develop according to the latest specifications.

When deploying they are faced with the sad reality, that version of the library is not available on the production server either because it is not approved by the Sys Admin team or simply it is not available

As result their code can not be deployed because it relies on a feature only the latest and greatest version provides!

Composer

It is to solve this issue that composer was created.

Its concept is scarringly simple, define a list of requirements and composer insures they are installed.

Those requirements are specified in JSON format on a file named composer.json

Composer is not like a traditional package manager, packages are installed locally The advantage is that we can have several applications using different versions of the same library, something that with a package manager like PEAR, apt-get or yum is impossible or at least extremely hard to achieve.

This is not a new concept, nodejs, ruby, python they all have it and now also PHP

Install and run

Composer can be installed by running the following command

curl -s http://getcomposer.org/installer | php

This will run a few system tests and install composer locally, on the current folder.

 

To run composer you can type:

php composer.phar install

The file composer.json is read and dependencies installed to the specified version.

This all all developers will use the same version of the libraries

if you want to update the dependencies to a newer version you can run

php composer.phar update

tip:

After the first run a file named composer.lock is created, this file lists installed versions of the dependencies. This file should be shared with all developers to ensure consistency


Defining dependencies

Lets say our project requires the twig templating engine. The only thing we need to do is editing the composer.json file and add the dependency, for example:

1
2
3
4
5
{
    "require": {
    "twig/twig" : "1.*"
    }
}

Just like that we told composer to install the twig's latest revision from version 1

Autoloading

Installing dependencies is the first step, but what good it is if PHP can not find them?

Composer takes care of that for us and supports any library that complies with the PSR-0 standard.

You just need to include the file vendor/autoload.php in your application and magically all dependencies will be available.

require "vendor/autoload.php";

Packagist

Packagist is an online repository for PHP libraries, much the same way PEAR is.

There we can browse through the vast list of libraries that composer can install for you.

Go to http://packagist.org and check

Private libraries or dependencies

All this works well for new projects but what about existing projects with libraries that where nor prepared fro composer or private libraries that we do not want to make available to the public?

Composer also supports it you just need to provide the relevant information about your packages.

Lets define our XPTO private package.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "XPTO",
                "version": "0.0.1",
                "source": {
                    "url": "http://svn.foo.com/svn/xpto/",
                    "type": "svn",
                    "reference": "trunk"
                }
            }
        }
    ]
}

The node repositories is the key, here we can add several repositories to composer, in our case we will add repositories of the type package.

The structure is straightforward, reach repository has a type,as we are defining a repository for a package we conviniently state that the type is package.

Next we provide information about the package itself, we give it a name, version and tell composer where to find it with the source property.

The source has three child properties, the url defiles the root of the repository, the type tells composer the type of CVS user and the reference point to a tag, branch, or commit

Tip:

Packages should use semantic versioning so that your users know what to expect from an upgrade


 

Lets see a complete composer.json that includes twig and our XPTO package

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"repositories": [
    {
        "type": "package",
        "package": {
            "name": "xpto",
            "version": "0.0.1",
            "source": {
                "url": "http://svn.foo.com/svn/xpto/",
                "type": "svn",
                "reference": "trunk"
            }
        }
    }
],

"require": {
        "twig/twig" : "1.*",
        "xpto": "*"
    }
}

Even more awesomeness

A cool feature for composer is that it can bootstrap a project for you, with a simple command all dependencies are download and installed without the need to create the composer.json file.

This is a real time saver, you can easily set up your projects so that other developer can have a working installation by executing a simple command

php composer.phar create-project francodacosta/phmagick

will install phmagick and its dependencies. A more usefull example would be to install Symfony 2 framework

composer.phar create-project symfony/framework-standard-edition symfony2

You will end up with Symfony 2 installed on a folder named symfony2.

I hope that this article has inspired you to start managing your dependencies in an organized fashion.