Composer.json explained in relation to Drush Make

Last updated on
22 July 2020

Background

A Drupal project usually consists of the following:

  • Drupal Core
  • A number of modules and maybe a base theme downloaded from Drupal.org
  • Perhaps even some PHP libraries found on GitLab, GitHub or BitBucket
  • Custom code written by you and your team mates

Previously, the most popular way to assemble all these parts has been Drush Make. In recent years the PHP Community has gathered around Composer, which is now used to manage the Drupal 8 core dependencies.

Getting started

Using Composer to Install Drupal and Manage Dependencies

Explanation of composer.json 

Composer has a great introduction and thorough documentation of the composer.json format.

Packagist

Composer retrieves information from packagist.org to download packages, Drupal projects are not listed on Packagistinstead, Drupal.org provides its own repository of composer metadata for Drupal projects.

The Composer template, already includes it in therepositories ofcomposer.json:

"repositories": [
    {
        "type": "composer",
        "url": "https://packages.drupal.org/8"
    }
],

Core version

In Composer, Drupal core is a package like any other. So it is added to your project by adding a dependency to your composer.json.

Adding the following information to the composer.json will download the latest Drupal 7 release and place it in the web/-folder of the Composer project.

{
    "require": {
        "composer/installers": "~1.0",
        "drupal/drupal": "7.*"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/7"
        }
    ],
    "extra": {
        "installer-paths": {
            "web/": [
                "type:drupal-core"
            ]
        }
    }
}

With Drupal 8 we can choose the same approach ("drupal/drupal": "8.*") or we can use the subtree-split of the core-directory ("drupal/core": "8.*").

You can use the ready to go template for each version: Branch 8.x for Drupal 8 or Branch 7.x for Drupal 7

Projects

All Drupal projects to be retrieved should be added as dependencies in semantic versioning format.

The following will download the Chaos tool suite (ctools) module version 1.4 for Drupal 7.

{
    "require": {
        "drupal/ctools": "1.4"
    }
}

The module will be placed under sites/all/modules/contrib/.

You can also run php composer.phar require drupal/ctools from the command line in the root directory of the project. This will prompt for any additional information needed and update composer.json accordingly.

Since many Drupal projects are not available from the default Composer package repository Packagist, they will be downloaded from the Drupal repository defined in the composer.json

Project options

Version

You can specify the version of each project using Composer package version constraints.

Subdir

Using the Composer Installers plugin you can customize the path of individual projects or by type. Therefore you will need to specify the installer-paths section of composer.json.

{
    "extra": {
        "installer-paths": {
            "sites/all/modules/contrib/{$name}/": ["type:drupal-module"],
            "sites/all/themes/{$name}/": ["drupal/zen"]
        }
    }
}

You can review the default paths of Drupal 8 Template or Drupal 7 Template

Patch

Patching is not natively supported by Composer. For implementing patches in the composer workflow you can use a composer plugin; cweagans/composer-patches is the standard patch manager recommended for use with Drupal projects.

Example

The following example shows usage with composer-patches plugin.

To apply a patch to a project a patches section must be added to the extras section of composer.json.

The following will patch the domain_conf module with this patch:

{
    "extra": {
        "patches": {
            "drupal/domain": {
                "Domain_conf permissions": "https://www.drupal.org/files/issues/domain-conf-450688-%2310.patch"
            }
        }
    }
}

The plugin generates a PATCHES.txt file for each patched project as Drush Make does.

Location

Specifying alternate release information for projects is possible by setting up a custom repository using Satis.

Type

The type has to be specified in the composer.json of the Project (Module, Theme,...). Drupal Packagist takes care of that for Drupal.org Projects. If you are maintaining a custom composer.json you have to specify the the package type on your own to one of the types supported by the Composer Installers plugin. This includes drupal-module and drupal-theme.

This is necessary to let the installer place the project in the correct directory, when it is required "composer/installers": "~1.0".

Directory name

Projects can be placed in specific directories when using the Composer installers. See Subdir.

l10n_path

Composer does not support specifying custom paths for translations.

l10n_url

Composer does not support specifying custom translation servers.

overwrite

Composer always does install or update packages in the given path, when necessary. So there is no need for an overwrite flag.

On the other hand, if you want to make sure certain files or folders should not be overwritten, you could use the Composer preserve paths plugin.

translations

Composer does not handle translations.

Project download options

To download a project which is not on Drupal.org or a Composer package then define it as a custom package repository and add it as a dependency.

This method supports version control checkouts from custom branches or tags as well as file downloads. Also, this is useful if a module from a sandbox is required.

Libraries

If libraries are not available from a composer repository, they can be retrieved by specifying custom packages in the repository section. See Project download options.

Example downloading the Chosen v1.8.7 library:

when you add this to the existing `repositories` section, you will end up with this. The bit that you are adding is in bold

{
"repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        {
            "type": "package",
            "package": {
                "name": "harvesthq/chosen",
                "version": "1.8.7",
                "type": "drupal-library",
                "dist": {
                    "url": "https://github.com/harvesthq/chosen/releases/download/v1.8.7/chosen_v1.8.7.zip",
                    "type": "zip"
                },
                "require": {
                    "composer/installers": "~1.0"
                }
            }
        }
    ],
}

after you add this, please also add the following line to the existing `require` section directly below it

"require": {
        "harvesthq/chosen": "1.8.7"
    }

Note: A different package type is introduced here: drupal-library. This allows Composer Installer to handle library placement differently from modules and themes.

Library options

Libraries are defined as Composer packages and thus support the same options as Drupal projects and Composer packages in general.

Destination

Libraries can be placed in specific directories using the installer-paths section. See Subdir.

Includes

Composer uses dependencies as includes. If a dependency has dependencies on its own and specifies these in its' composer.json file then these dependencies will be installed as well. Note that a Composer package does not have to contain any actual code. You can even specify packages of type metapackage to specify dependency-wrappers that do not even install and only hold additional dependencies in the require section.

Note: some schema properties are only used in the root composer.json. They are marked as root-only in the documentation.

Defaults

Composer does not have the concept of user-defined default values for packages. Nonetheless, Composer Installer does support setting a standard directory for all packages of a specific type (e.g. drupal-module). See Subdir.

Overriding properties

Composer does not support overriding individual properties for a package.

One approach to changing properties is to fork the package, update the composer.json for the package accordingly and add a new repository pointing to the fork in the root composer.json.

Packages overriding the Drupal projects repository should be placed before the Drupal.org repository, due to the order in which Composer looks for packages.

Recursion

Composer resolves dependencies only in the context of the provided composer.json package information. It does not look for dependencies in other composer.json files, for example in subdirectories of the downloaded packages.

In addition a few properties are only defined by the root package - the composer.json for the project.

Generate

Using the "Composer Generate" drush extension you can now generate a basic composer.json file from an existing Drupal 7 project.

FAQ

How is this better than Drush Make?

Drush Make has its own problems which makes it difficult to work with e.g.:

Also Drush Make is a tool primarily built for Drupal. Using Composer means using the same tool that many others in the PHP community use and makes it easy to use other libraries with a Drupal project.

See also: Composer instead of drush make to build projects (Lullabot)

Should I commit the contrib modules I download

Composer recommends no. They provide argumentation against but also workarounds if a project decides to do it anyway.

Credit

The initial document was created by kasperg, revised by webflo, derhasi and albertvolkman. It was moved from https://github.com/drupal-composer/drupal-project after that.

Using Composer to manage a Drupal project would not be possible without the work of others. Some projects are mentioned above. 

Help improve this page

Page status: No known problems

You can: