Better dependency management: leverage composer to the limit

Can I use composer to do this?

A talk by Rodrigo Aguilera / @marinero


Focused on processes, workflows and shared tools


  • The PHP reinassance
  • The old days of drush make and the Drupal island
  • Composer is awesome
  • Your drupal project has dependencies too
  • Compose all the things!

The PHP reinassance


We had too much code

Took less time to write (or copypaste) a solution yourself than to find a component you can reuse.


Sharing must be easy or it won't happen.

Free software as a feature.

First attemps, aka: the way there

  • Pear (PHP 4, required root, lots of includes)
  • Class autoloading (PHP 5.0)
  • Github (As replacement of Sourceforge)
  • Namespaces (PHP 5.3)
  • PHP standards (PSR-x) from PHP-FIG

The drupal island

Drupal diver

Drush make (2010)

The shopping list

api = 2
core = 7.*
projects[views] = 3.1
projects[ctools] = 1.0-rc1
projects[media] = 2.x-dev

projects[nodequeue][subdir] = contrib
projects[nodequeue][version] = 2.0-alpha1
projects[nodequeue][patch][] = ""
projects[nodequeue][patch][] = ""

libraries[jquery.cycle][download][type] = get
libraries[jquery.cycle][download][url] =
libraries[jquery.cycle][destination] = libraries


  • Downloads all the code everytime
  • All dependencies listed
  • You have to be specific about the versions
  • Only remote patches
  • Different make files for different purposes

Some brave sailors

Drupal diver Sailorwoman

Drupal makes some friends out there

Just by looking at the composer.json in drupal core

  • A lot of symfony components(dependency injection, events, routing, yaml, etc)
  • Twig
  • Guzzle
  • Composer
  • And much more

Introducing Composer - 2012



The main goals

  • Reuse third party libraries.
  • Avoid dependency hell.
  • Standarization among PHP projects


Composer is a tool for dependency management in PHP. It allows you to declare the dependent libraries your project needs and it will install them in your project for you.

What it means

  • No more Copy/Paste of libraries
  • Resolves dependencies
  • Each project defines its own requirements
  • Performs build tasks
  • Autoloading: all code under the same roof

Similar to composer in diferent programming languages

  • npm (javascript)
  • pip (python)
  • rubygems (with bundler)

Get Composer

# Quick-n-easy:
$ curl -sS | php

# Global
$ curl -sS | php -- --install-dir=bin

Structure of composer.json

Base manifest file for your project

    "name": "rodrigoaguilera/mydrupalsite",
    "description": "This site is awesome.",
    "require": {
        "drupal/honeypot": "1.*"
    "require-dev": {
        "drupal/devel": "1.*"
    "config": {},
    "extra": {}

Composer.json and composer.lock

  • The lock file has the dependencies already solved.
  • The key to get everyone same versions is the lock file.
  • Always commit your lock file.

Basic Commands


composer install

Reads composer.lock and downloads all your dependencies in the /vendor directory.


composer update [<vendor>/<package>]

Writes a new composer.lock based on what is on composer.json and downloads only what is missing.
You can update only one package to do more atomic updates.


composer require <vendor>/<package>:"<version-constrain>"

Origin of libraries, modules, tools, etc.

The concept of repositories.

Main repository for packages.
There is also as a mirror of the modules and themes on

Execute binaries


composer exec drush

Global vs local

  • The power of composer comes from having per project dependencies.
  • But you can also install composer plugins or tools shared by all the projects in your machine.
  • Use "composer global" before commands. (needs environment variable $COMPOSER_HOME to be set)

Simulating environments

"config": {
    "platform": {
       "php": "5.6.2",
       "ext-mongodb": "1.1"

Semantic versioning


Composer in production

composer install --prefer-dist --no-dev --optimize-autoloader
  • No git repository files
  • The require-dev section is ignored
  • Faster autoloader

Component vs. project

The composer.json for a project (the root package) has more capabalities like:

  • Use your own repos
  • Define hook scripts (post-install, pre-update, etc.)
  • Configuration


  "require": {
    "cweagans/composer-patches": "~1.0",
    "drupal/drupal": "8.5.*@dev"
  "config": {
    "preferred-install": "source"
  "extra": {
    "patches": {
      "drupal/drupal": {
        "Add startup configuration for PHP server": ""


Quiz: install or update

  • Be sure you have the last updates from your team: composer install
  • Deploying a new release of your application to production. composer install
  • Checked out with git a new project and want to start coding. composer install
  • Fetch new versions for the dependencies of your project. composer update

But... How do I use composer in my drupal project?

Composer template for drupal projects comes to the rescue.

What does the template do?

  • Drupal will be downloaded with correct permissions ready for install.
  • Declaring a new depencency and downloading is one semantic command.
  • Modules, themes, and profiles (packages of type drupal-[module|theme|profile]) will be placed in web/[module|theme|profile]/contrib/

What does the template do?

  • Creates default writable version of settings.php.
  • Latest version of drush is installed locally for use at vendor/bin/drush.
  • Latest version of DrupalConsole is installed locally for use at vendor/bin/drupal.

Profit :D

  • Now everyone can have not only the same modules but also drush and console
  • Updating all your modules to the stable versions is just a couple of words away
  • Your continous integration system can become much more simple

Frontend libraries are also dependencies

  • Not in packagist ( or bower)
  • Different locations than modules

  • Add one repository to your root composer.json
  • Collects both packages from npm and bower under 2 vendors
  • Enables the ability to do composer require npm-asset/bootstrap-sass:"^3"
  • Needs oomphinc/composer-installers-extender to define custom paths

Binary tools are also dependencies

  • Generally found in distribution's repositories (apt-get, yum, etc)
  • Usually compiled for a certain arquitecture and operating system
  • Specific packages for each binary
  • Available on vendor/bin/
  • Examples: mouf/nodejs-installer, jakoch/phantomjs-installer


Minimum stability for all the dependencies or one by one

For example:

              "minimum-stability": "dev"

You can be more semantic and declare it for each package like

               composer require "drupal/webform":"^5@beta",

Config options

"config": {
    "sort-packages": true,
    "discard-changes": true,
    "process-timeout": 600,
    "platform": {
      "php": "7.1.0"


Committing dependencies in the repo


The future

  • Better user experience
  • Best practices
  • Make parts of Drupal reusable for other PHP projects