Getting Started with Composer and Drupal 8

Drupal 8, like most modern PHP frameworks, depends heavily on code from external sources. In the past, site builders obtained these by downloading them manually, or by using drush make. Composer is the standard tool used in PHP projects for managing all of a site's dependencies, pulling code into a central place (the vendor directory) and avoiding conflicting versions. Composer is becoming the "downloader in charge" of Drupal 8 builds, downloading core, contributed themes and modules, and external libraries.

Quick Start

Install composer

See documentation on composer.org.

Create a complete Drupal 8 codebase.

composer create-project drupal-composer/drupal-project:8.x-dev some-dir --stability dev --no-interaction;
cd my-site;

Here's what that did:
The create-project command gets the requested project, uses it as a starting point for the new project, and runs install within the new project.

Using drupal-composer/drupal-project is recommended because it is configured to install packages in proper locations (like modules/contrib), enables patching, adds drush and drupal console, and makes updating drupal core straightforward.

More about locations set by the drupal-composer/drupal-project template:

  • in /vendor: all normal dependencies (regular composer packages)
  • in /web/modules/contrib: all packages of type drupal-module (all contrib drupal modules)
  • in /web/themes/contrib: all packages of type drupal-theme (all contrib drupal themes.
  • in /web/core: Drupal core, from drupal-composer/drupal-core
  • in /web: Assorted scaffolded files like index.php and .htaccess, from drupal-composer/drupal-scaffold

This expects /web to be configured as the web root on your server, keeping the vendor directory completely inaccessible to the public. This improves security, and is a common practice in other web frameworks.

Add a module or two.

composer require drupal/admin_toolbar;
composer require drupal/paragraphs;
composer require drupal/commerce;

Updates composer.json, downloads requested package and its requirements, and finishes by updating composer.lock and autoload.php. See commerce's composer.json file to see its listed dependencies, which are downloaded automatically by composer.

Remove a module.

composer remove drupal/paragraphs;
Note: this removes all dependencies required by the removed package that no other packages require.

Change version requirements for a module.

composer require drupal/paragraphs:^1.1;
Composer version docs
I remember the symbols like this: ^ goes higher than ~.
Drupal module/theme version 8.x-1.2.3 becomes version 1.2.3 to composer.

Themes work the same way as modules

They're both considered packages to composer.

composer require drupal/zen;

Committing changes and deploying

If you want to commit everything that composer downloaded, there are couple of things you need to do.

First, use the .gitignore from pantheon-systems/example-drops-8-composer to replace the .gitignore in the project root created by drupal-composer/drupal-project. The big difference is that it does not ignore the vendor, modules/contrib, and themes/contrib directories.

Second, delete any .git directories in subdirectories. The presence of these directories causes git submodules or subprojects to be created, instead of committing the actual code which is usally what is desired. Here's a command that's close: find . | grep "\.git" | xargs rm -rf. I've found that it deletes too much, including .gitignore files, so it should probably be updated to use egrep. Found originally on Montana Flynn.

Finally go ahead and commit everything that composer downloaded.

Collaborating with other developers

If using a version that does not include all dependencies (e.g. vendors), use composer install to get the same codebase as other developers. Specific versions used are loaded from composer.lock.

If newer versions of packages are available, you can retrieve them using composer update, e.g. composer update drupal/paragraphs. This accepts the same version restrictions as composer require.

General comparison to drush make

Similarities

  • 'make' system: assembles a codebase from a list of required elements.
  • For locating packages, drush make looks by default at drupal.org, composer looks by default at packagist.org. (If using drupal-composer/drupal-project, composer will also look at drupal.org.)
  • Support for applying patches.
  • Support for specifying versions, even specific commits, of dependencies.

Differences

  • Composer recursively reconciles dependencies. Drush make does not reconcile version requirements of multiple modules.
  • Composer places all elements in a common 'vendor' directory, avoiding duplicates. Drush make downloads into the folder containing each make file.
  • Composer auto-generates an autoload.php file so that all dependencies can be reliably loaded from any file. Drush make only downloads.

It's either/or for downloading

Once you set up a site using composer, only composer should be used for updating code. The traditional methods of using drush dl modulename or downloading and extracting archives become far too cumbersome, plus composer will not be automatically aware of the manual updates.

You can still use drush or drupal console for the usual things like updating the database, enabling modules, clearing caches. You just can't (or shouldn't) use them to download code for your site once you start using composer to assemble the codebase.

What composer is and isn't

  • It is a package dependency manager.
  • It is a code downloader and assembler. Like make, or drush make.
  • It is not an installer or enabler for Drupal.
  • Composer "install" only downloads code.
  • It does nothing with a site's database.
  • You don't install a site using composer. You assemble its codebase using composer.

What a composer project or package is

  • A composer project can represent an entire website's codebase.
    • drupal core
    • contrib modules, themes, profiles
    • 3rd party libraries
    • custom modules, themes, profiles
  • A composer project can represent a single module or theme or library, and what it depends on.

In the case of drupal-composer/drupal-project, the package contains drupal core, a scaffolded web root, and contrib modules and themes.

Bonus tip: default package repository

The default composer package repository is packagist.org. If repositories are listed in your composer.json file, these are searched for requested packages in addtion to packagist.org.

Here's an example of what that means. In the first example above, composer require drupal-composer/drupal-project, composer first looks at packagist.org for a package that matches drupal-composer/drupal-project. It finds it https://packagist.org/packages/drupal-composer/drupal-project, and sees that its code is at https://github.com/drupal-composer/drupal-project, so uses that as the download source.

The drupal-composer/drupal-project template includes an added repository listing: https://packages.drupal.org/8, which allows composer to find drupal projects without them having to have entries on packagist.org.

References and further reading

Good luck!

I hope this helps you get underway, using composer in your Drupal 8 builds. There's a lot more to cover, so let me know if you have any questions and I'll try to help. Use the comment form here, or find me @nadavoid on twitter, IRC, and the drupal and drupaltwig slacks.

[edited 2016-11-07 to incorporate feedback from @Mixologic]

Comments

One thing to note: using

One thing to note: using drupal-composer/drupal-project as your base, you are getting an additional composer repository of packages.drupal.org/8 which converts the project/module metadata into something more akin to library/package metadata that composer is used to dealing with. i.e. your comparison that "For locating packages, drush make looks by default at drupal.org, composer looks by default at packagist.org." isnt entirely accurate. Composer is consuming metadata from drupal.org that follows the same api as satis, toran proxy, and packagist.org. More details can be found at https://www.drupal.org/docs/develop/using-composer

Thanks for that note

Thanks for that note @Mixologic. I updated that bullet point and added a bit in the bonus tip to help clarify repositories.

Thanks, this helped me grasp

Thanks, this helped me grasp a few things I missed. What I'm working on right now is how to take over a project that's only partly managed by composer. So we need to fix composer.json to pull all dependencies and do something to the autoloader too. Somehow get it to a state where composer can be used primarily, and in a Pantheon repo. Without starting over, I'd hope. Or would starting over be easiest?

Glad it helped. I would

Glad it helped. I would expect it to be doable to get your site fully under composer control by updating what you have, rather than starting over. I'd suggest studying the composer-project json file to incorporate its elements into your composer.json file. You might also find interesting this Composer on Pantheon I just posted.

And get your feed on Planet

And get your feed on Planet Drupal! This is great stuff to share.

https://www.drupal.org/drupalorg/docs/content/planet-drupal