TSM - Composer and Packagist – PHP’s Superstars

Radu Murzea - PHP Developer

PHP has a shaky history as far as package management goes. All this was about to change in the first part of the year 2012, when the Composer and Packagist were launched. In this article, we will explore the beautiful world and history of modern package management in PHP.

A little history

No package manager existed in the PHP world until, in 2000, Stig Bakken started the PEAR project, as a result of the conversations that took place at the PHP Developers Meeting conference in Tel-Aviv.

PEAR's workflow was to include the package manager directly in the PHP runtime and have the user install the dependencies using the command-line. These dependencies were downloaded as ZIP files and they were imported in the PHP code by the use of "include" and "require" statements.

In order to improve performance, PECL was launched in October 2003. This system allowed compiling PHP code into C binaries and then being used through PEAR as PHP extensions. The reasoning behind this was that C binaries have superior performance compared to interpreted PHP code.

Sharing code through PEAR and PECL was difficult due to a lack of coding standards, difficult contribution to existing projects and the tedious way in which the libraries and extensions could be used. Despite all this, PEAR's popularity grew because it was the only available option.

Due to its many disadvantages, most programmers simply decided not to use this package manager at all and instead relied on what functionality their framework provided. It was especially encouraged during the PHP frameworks boom during 2004 - 2006. This decision resulted in an excessive coupling between the framework and the application being developed, which in turn made migrating to a different framework extremely difficult and costly.

All this leads us to 2009, a year with a significant historical meaning in the PHP world. Two major events happened at that time:

Suddenly, these changes eliminated most drawbacks of PEAR and paved the way to the modern PHP ecosystem that we know today.

Among other things, the development of the Composer and Packagist project started; their first stable release was in March 2012. These projects were developed by Nils Adermann and Jordi Boggiano, the two continue to maintain them to this day.

How it works

composer.json

In order to use Composer in a project, we need to create a file called composer.json. This file will contain descriptions about what packages our projects depends on, but it can contain a lot more information.

One of the most important elements in this file is the key require. Under it, we specify what packages our project depends on:

"require": {  
 "monolog/monolog": "1.0.*"
}

A lot of times, this is all we need to specify our dependencies. For the complete list of options that can be specified in the composer.json file, you can take a look at the documentation.

In addition to external packages, we can also specify platform packages as dependencies. These are virtual packages that represent various resources installed on the host system:

To see what platform packages are available on our system, we can use the composer show --platform command.

Installing packages

Installing the packages is done by running the composer install command.

When this is first executed, Composer will try to figure out which version of each package to download so that all version and stability requirements are satisfied. This can be a difficult task because, in practice, many packages depend on each other and these inter-dependencies will be specified in different ways (see the chapter about version operators for more details).

The way Composer solves this is through a boolean satisfaction algorithm. Therefore, this is a problem whose complexity grows exponentially as the number of dependencies increases.

composer.lock

After running the install command, we'll notice that a new file was created: composer.lock. The purpose of this file is to store the exact versions of the packages that Composer installed by doing a "lock" of these versions (hence the file name). By doing this, all programmers who will use the project will have the exact same dependencies versions installed.

The .lock file contains a hashed version of the .json file. This means that, if the .json file is changed, the next execution of composer install will point out that the 2 files are no longer in sync.

Having such a file also makes installing the packages easier because composer install will skip the complex step of figuring what version to download for each package.

Versioning Operators

Semantic versioning (major.minor.patch) is now considered a best-practice in the PHP world. Therefore, packages generally follow these guidelines.

The version of a package can be specified using basic operators:

In addition to these basic operators, next release operators can also be used:

Package stability

Composer allows installing packages with various levels of stability. The possible stability levels, in increasing order, are: dev, alpha, beta, RC and stable. This level can be specified in 2 not mutually exclusive ways:

Autoloading

In the chapter about the history of package management, we saw how the full and correct support for namespaces added in PHP 5.3 was the spark that allowed the birth of a truly useful package manager. Namespaces are, among other things, the correct way to integrate 3rd-party code in our own application, eliminating the need to use the include and require statements.

Composer will build a namespace autoload for our project and our dependencies based on the information specified in composer.json under the autoloading root-key. This information can be specified in 3 different ways: PSR-0 definitions, PSR-4 definitions and mapping between a namespace and a file. These 3 possibilities can be added in any combination one chooses.

Package sources

Packagist

Packagist is the main and default repository which contains all the available packages that can be installed. These are usually added there and maintained by their authors. Packagist requires that the source of a package be a Git repository, which of course must be public. Because of this, the source usually ends up being the package's GitHub page, but this is not mandatory.

Satis

Satis is a simpler incarnation of Packagist, it can be installed in a private system. There are two main benefits for using Satis as package repository:

Commands

Until now, we met some of Composer's features through the commands install and show. However, Composer has a variety of other commands.

In short, commands help us easily perform a variety of the most frequently needed operations in the context of a package manager. This could include starting a new project, adding/deleting packages, checking dependencies between packages, re-generating autoload information, changing Composer settings and many more. We will let you check the documentation to see a very detailed description.

In the end...

Composer, together with Packagist, is a modern and solid package manager. It includes a lot of needed features, without sacrificing simplicity and easy learning curve.

Composer was the spark needed by PHP in order to adopt many modern software development practices. It's by far one of the most important projects in PHP's ecosystem.