logo-composer-transparent

Composer is a tool for dependency management in PHP. It allows us to declare the libraries (packages from now on) on which our project depends on and downloads them for us. With many high quality packages available to us, the are redefining they way we are building PHP software. You can browse through the wide variety of packages at the composer main repository packagist.org.

Composer is a simple tool to use and this tutorial will go over the installation and usage basics.

Installation

Windows

The easiest way to install Composer in a Windows machine is download and run the Composer installer. It will also set up the %PATH% for you so it can be used from any directory in the command line.

*nix

In Unix-based systems like Linux or MacOS the installation is done downloading the installer – which is a PHP script, using cURL, and then executing it. The installer will check our PHP settings to make sure Composer can be installed in the machine. It will then download our composer.phar file, the Composer executable. Below is the code you need to run to accomplish this:

$ curl -sS https://getcomposer.org/installer | php

If you want to install Composer globally, you have to place the composer.phar file into one of the directories included in the PATH environment variable:

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

How it works

Composer is a per-project dependency manager, which means that the packages needed by our project are not going to be installed globally. Packages will be downloaded and placed in a special folder called vendor. Then, by adding a require_once to the Composer autoload file, you will provide access to all your dependencies.

Dependencies are defined in a file called composer.json, and in its simplest version looks like this:

{
    "require": {
        "fabpot/goutte": "v1.0.5"
    }
}

In the above example, we defined a dependency, the “fabpot/goutte” package, which is a screen scraping and web crawling library for PHP.

When we execute “composer install”, Composer checks the required dependencies and downloads the packages:

$ composer install
Loading composer repositories with package information
Installing dependencies (including require-dev)
  - Installing symfony/event-dispatcher (v2.4.2)
    Downloading: 100%

  - Installing guzzle/common (v3.8.1)
    Downloading: 100%

  ...

  - Installing symfony/browser-kit (v2.4.2)
    Downloading: 100%

  - Installing fabpot/goutte (v1.0.5)
    Downloading: 100%

symfony/event-dispatcher suggests installing symfony/dependency-injection ()
symfony/event-dispatcher suggests installing symfony/http-kernel ()
Writing lock file
Generating autoload files

As you see, Composer downloaded “fabpot/goutte”, but also a few other packages. This is because the “fabpot/goutte” package has other dependencies too – they can be found in the composer.json file of the package -, but we don’t have to worry about it, Composer takes care of it and calculates the dependency graph automatically. This can become an expensive process when the number of dependencies increases. Composer deals with this by creating a composer.lock file with the exact versions of all the packages that must be downloaded, so the next time we run “composer install”, Composer will just read the composer.lock file and will download the packages. If we edit the composer.json file, we will need to run “composer update” so the composer.lock file gets recalculated.

“composer update” is the new “compiling…” :)

Once the packages have been downloaded, Composer generates a php file we need to include in our projects to use the dependencies. This file registers a PSR-0/PSR-4-compliant autoloader, so we don’t need to require any class file separately:

<?php
require_once __DIR__.'/vendor/autoload.php';

use Goutte\Client;

$client = new Client();
$crawler = $client->request('GET', 'http://www.servergrove.com');

$title = $crawler->filter('head > title')->text();
echo $title;

In the above example, we require the autogenerated autoload.php file, and then used the Goutte\Client class of the “fabpot/goutte” package to extract the contents of the title tag from the ServerGrove website.

The composer command

We have talked about the “install” and “update” commands, but Composer provides a few more commands. “composer list” displays a list of all available commands:

$ composer list
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
...

Available commands:
  about            Short information about Composer
  archive          Create an archive of this composer package
  config           Set config options
  create-project   Create new project from a package into given directory.
  depends          Shows which packages depend on the given package
  diagnose         Diagnoses the system to identify common errors.
  dump-autoload    Dumps the autoloader
  dumpautoload     Dumps the autoloader
  global           Allows running commands in the global composer dir ($COMPOSER_HOME).
  help             Displays help for a command
  init             Creates a basic composer.json file in current directory.
  install          Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.
  licenses         Show information about licenses of dependencies
  list             Lists commands
  require          Adds required packages to your composer.json and installs them
  run-script       Run the scripts defined in composer.json.
  search           Search for packages
  self-update      Updates composer.phar to the latest version.
  selfupdate       Updates composer.phar to the latest version.
  show             Show information about packages
  status           Show a list of locally modified packages
  update           Updates your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  validate         Validates a composer.json

Some interesting commands:

  • init: Creates a basic composer.json interactively
  • validate: Checks whether the composer.json file is valid
  • selfupdate: Updates Composer itself to the latest version. If the Composer version is too old – 30 days or more -, a warning will be displayed when executing any command.
  • search: Look for packages in Packagist – e.g. “composer search yaml” -.
  • show: Displays information about packages. For example, “composer show –installed” to show installed packages.
  • create-project: Creates a new project from a package, especially useful for frameworks – e.g. to create a new project with the Symfony 2.4.2 framework: “php composer.phar create-project symfony/framework-standard-edition path/ 2.4.2″.

Package versions

There are several ways to define what version of a given package we want to use:

  • Exact version: “1.4.2″, “v1.4.2″.
  • Ranges: “>=1.0,<2.0″, “>=1.0,<1.1 | >=1.2″.
  • Wildcard: “1.0.*”, “1.*”.
  • Next Significant Release: “~1.2″ is equivalent to “>=1.2,<2.0″.

Stability

Every package version has a stability flag indicating whether it is “final” version or previous one such as, development, betas, alphas or release candidates. By default, only stable package versions are considered, so if we need something that is not in the stable level, the minimum-stability setting must be changed. Available values are “dev”, “alpha”, “beta”, “RC” and “stable”. It is also possible to set the minimum stability flag by dependency, appending “@flag” to the package version – e.g. “”fabpot/goutte”: “1.0.*@dev””.

The vendor directory

The vendor directory is created automatically by Composer and it should be ignored in your VCS system – e.g. .gitignore in GIT-. It is highly recommended to include the composer.lock file in the VCS, so everyone in the team have the exact same package versions. No more “it works on my machine…”!

More information

This is just a simple introduction of using Composer to manage our project dependencies. Composer has  excellent documentation, both for package consumers and publishers.

This post is also available in: Spanish