Drupal Composer recipes

In this post we are going to share some Composer recipes we collected while working with Drupal projects created from the Drupal Composer template. Also, we will take a look on how to convert an existing Drupal project to a Composer project.

If you still don't use Composer for managing Drupal projects, you should start doing this right now! The Drupal Composer template will help you to set things up. It's really easy to setup a new project.

If you’re still not convinced, check out the benefits of the Drupal Composer workflow:

  • No need to store contrib code (and the core!) in your version control system.
  • A single package management tool for everything: Drupal core, contrib modules, JS libraries, your own shared modules, etc.
  • Patching of core and modules is easier than ever.
  • It's way simpler than git submodules.

(All recipes consider Drupal 8, but they should work for Drupal 7 as well)

Installing contrib modules

  • composer require drupal/<MODULE_NAME>:~8.0 to get the latest stable version (or latest dev, if there is no “stable release")
  • composer require drupal/<MODULE_NAME>:dev-<BRANCH_NAME> to get the latest dev version
  • composer require drupal/<MODULE_NAME>:dev-<BRANCH_NAME>#<COMMIT_HASH> to get the exact version

Updating Drupal core/modules

  • composer update to update everything
  • composer update --dry-run to check for updates
  • composer update drupal/<MODULE_NAME> to update a single module

Patching packages

The cweagans/composer-patches plugin (which comes with the Drupal Composer template) will take patches from the "extra" section of the composer.json file:

   "extra": {
       "patches": {
           "<PACKAGE/NAME>": {
               "<PATCH DESCRIPTION>": "<PATH/TO/PATCH/OR/URL>",
               ...
           },
           ...
       }
   }

Example:

   "extra": {
       "patches": {
           "drupal/core": {
               "Fix language detection": "patches/2189267-24.patch"
           }
       }
   }

After a new patch is added run:

  • composer install to apply patch
  • composer update nothing (or composer update --lock) to make the composer-patches plugin write necessary changes to the composer.lock file

Installing custom/forked modules from Github

For the case when a module repository contains its own composer.json

Register the repository in the "repositories" section of the composer.json file:

   "repositories": [
       {
           "type": "vcs",
           "url": "https://github.com/<REPOSITORY/NAME>"
       },
       ...
   ],

Use composer require drupal/<MODULE_NAME>:dev-<BRANCH_NAME>#<COMMIT_HASH> to install the module.

For the case when the composer.json file is missing from the module repository

You'll need to use a bit more verbose variant:

   "repositories": [
       {
           "type": "package",
           "package": {
               "name": "drupal/<MODULE_NAME>",
               "version": "dev-custom",
               "type": "drupal-module",
               "source": {
                   "type": "git",
                   "url": "git@github.com:<REPOSITORY/NAME>.git",
                   "reference": "<BRANCH-NAME>"
               }
           }
       },
       ...
   ],

Use composer require drupal/<MODULE_NAME>:dev-custom#<COMMIT_HASH> to install the module.

For the case when the destination path should be different than modules/contrib

In addition to the above recipes, use the composer/installers plugin:

   "extra": {
       "installer-paths": {
           "web/modules/custom/<MODULE_NAME>": ["drupal/<MODULE_NAME>"],
           ...
       }
   }

Adding a JS library

Most popular libraries can be added easily with composer as they exist on Packagist. The tricky part is that most Drupal modules require that libraries are saved under the "libraries" directory while Composer installs them to "vendor". The composer/installers plugin can override package paths, but only for packages that depend on it. So, you'll need to override the composer.json file of the library stating that it has the composer/installers dependency.

Let's take a look at an example:

   "repositories": [
       {
           "type": "package",
           "package": {
               "name": "enyo/dropzone",
               "version": "4.3",
               "type": "drupal-library",
               "source": {
                   "url": "https://github.com/enyo/dropzone.git",
                   "type": "git",
                   "reference": "master"
               },
               "dist": {
                   "url": "https://github.com/enyo/dropzone/archive/v4.3.0.zip",
                   "type": "zip"
               },
               "require": {
                   "composer/installers": "~1.0"
               }
           }
       },
       ...
   ],  
   ...   
   "extra": {
       "installer-paths": {
           "web/libraries/{$name}" : ["type:drupal-library"],
           ...
       }
   }

After the above is added to the composer.json, run composer require enyo/dropzone:4.3 to download the library. Also, here we have used the exact version and added the "dist" section to make it possible for Composer to download a zip archive instead of cloning the Git repository.

Switch a dependency package to a forked version

Add the forked repository to the composer.json:

   "repositories": [
       {
           "type": "vcs",
           "url": "https://github.com/<REPOSITORY/NAME>"
       },
       ...
   ],

Run composer require <PACKAGE/NAME>:dev-<BRANCH_NAME>#<COMMIT_HASH>

Update an existing Drupal 8 project to use Composer

  • Make a backup ;)
  • Delete everything that will be managed by Composer: Drupal's "core" folder, contrib modules, etc.
  • Delete all Drupal "root" files, such as index.php, update.php, README.txt... All of them.
  • Create "web" directory in the project root and move all remaining Drupal folders (sites, modules, themes, libraries, profiles, etc.) into it.
  • Copy the Drupal Composer template files to the project root.
  • Prepare a list of Drupal core and contrib module versions (and everything else that will be managed by Composer) that are used currently on the project. Then run composer require specifying every dependency with the exact version. You'll need to convert Drupal versions into Composer versions, here are some examples:
    • drupal/core:8.1.8 is obvious
    • drupal/admin_toolbar:8.1.15 refers to admin_toolbar 8.x-1.15
    • drupal/ctools:8.3.0-alpha26 refers to ctools 8.x-3.0-alpha26
    • drupal/config_installer:dev-8.x-1.x#a16cc9acf84dd12b9714def53be0ce280a5b0c1a refers to config_installer dev snapshot made from the a16cc9a commit of the 8.x-1.x branch
  • Manually update versions of Drupal core and contrib modules to "~8.0" in the "require" section of the composer.json file. That will make updates possible.
  • Run composer drupal-scaffold which will create the Drupal "root" files.
  • Make your webserver use "web" directory as the web root.
October 17, 2016
7 Comments

Get our Newsletter






Comments

Thanks - so much of that seems to reflect what we've settled on too, but it's helpful to see some of it explained clearly though.

FYI - instead of 'composer update nothing', you can use 'composer update --lock', which I think is a bit clearer.

By James Williams
8 months ago

Thanks James,

I added 'composer update --lock' variant to the blogpost.

By Alex Tkachev
8 months ago

I wish this article was around when I was figuring this stuff. Still, a great reference. Thanks.

By Cleaver Barnes
8 months ago

I just had to add dropzone lib via Composer. But using composer installer as mentioned above was not enough. The packagist repository preferences overruled my settings and dropzone was installed to the vendor folder. The solution was--in my case--to use a custom package name. Instead of "enyo/dropzone" I used "dropzonelib/dropzone".

By thamas
8 months ago

Thank for great article!
How do I make my webserver use "web" directory as the web root? I'm on a shared hosting, cpanel. Redirect?

By Henrik
2 months ago

Hi Henrik,

I'd say ask your hosting provider how to do it. It really depends on the hosting.

By Alex
2 months ago

Wonderful article. One warning: make sure all your patches are listed in the extra / patches section because composer update --lock will first delete the project and then reinstall it so it can be patched. This is the right thing to do but be mindful of it.

By chx
3 weeks ago

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
icon
What is Amazee Labs?