Composer and Drupal

What is composer?

Composer is a popular tool for managing package dependencies in PHP. It allows you to define which libraries or packages you are going to use in your project, to build a dependency tree for them and to install all these with the right versions. Mainly it's being done using the single composer.json file, where all this project-information is written. In Drupal, there are also ways to define which modules, themes, and libraries our project is going to depend on. The well known drush.make file stores all the information about modules, libraries and their versions. These modules or libraries are being loaded and installed manually or using drush - a command line shell and Unix scripting interface for Drupal. At the end of April 2016, Drupal.org launched the Alpha of their Composer façade, providing Composer repository endpoints for Drupal 8 and Drupal 7 on Drupal.org. It's a great step to the larger frame of the whole PHP community and projects (as opposed to just the Drupal community on drupal.org and using Drupal-specific interfaces like drush). In this article I am going to show the process of composing Drupal project: that's called a Composer style.

Package Repositories

Package Repository is an endpoint where Composer looks for the packages that we want him to download. At the moment of writing this article, Drupal.org projects are not yet aggregated by the Packagist repository, which is the default repository of package meta data used by Composer. Therefore, to be able to work comfortably with Composer when setting up your Drupal project, you will need to add Drupal.org as a Composer Repository to your composer.json file within your future Drupal root folder. Drupal.org provides two separate composer repository endpoints, which are now in alpha: one for Drupal 7 and another for Drupal 8. There is also a Drupal Packagist package repository, which is scheduled to be deprecated in January 2017, or when the official Package Repository from Drupal.org is ready. It won't receive any updates for the modules and themes after the official Drupal.org Package Repository Release. So, in order to work comfortably with Composer in Drupal, we need to add one of the three following urls to our composer.json:

Let's try adding the official Drupal.org Package Repository to our composer.json. What we need to do is to execute the following commands: 1) create an empty composer.json

composer init --no-interaction

2) add a package repository

composer config repositories.drupal composer https://packages.drupal.org/8

And here is an example of how our composer.json file will look like:

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

Once you have added the appropriate Drupal.org composer endpoint for the version of Drupal you want to use, you can use Composer as you would use it for any other PHP project.

Installing Drupal

Well, as far as Drupal Composer repositories are only moving now towards steadiness, the only option we have so far after specifying our Package Repository (and which is already working like a charm) is installing the Drupal of the specific version. For starting a new Drupal installation from scratch, we will have to execute the following command:

composer create-project drupal/drupal my_project 8.1.*@dev

After executing this line in our shell, the composer will download the Drupal of the given version and place it in the my_project directory. The interesting part now is that there will be a new composer.json file inside of this my_project directory. Let's take a closer look at it.

{
    "name": "drupal/drupal",
    "description": "Drupal is an open source content management platform powering millions of websites and applications.",
    "type": "project",
    "license": "GPL-2.0+",
    "require": {
        "composer/installers": "^1.0.21",
        "wikimedia/composer-merge-plugin": "~1.3",
    },
    "replace": {
        "drupal/core": "~8.1"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "preferred-install": "dist",
        "autoloader-suffix": "Drupal8"
    },
    "extra": {
        "_readme": [
            "By default Drupal loads the autoloader from ./vendor/autoload.php.",
            "To change the autoloader you can edit ./autoload.php."
        ],
        "merge-plugin": {
            "include": [
                "core/composer.json"
            ],
            "recurse": false,
            "replace": false,
            "merge-extra": false
        }
    },
    "autoload": {
        "psr-4": {
            "Drupal\\Core\\Composer\\": "core/lib/Drupal/Core/Composer"
        }
    },
    "scripts": {
        "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
        "post-autoload-dump": "Drupal\\Core\\Composer\\Composer::ensureHtaccess",
        "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup"
    }
}

There is a couple of things here to pay attention to: First of all, there are few requirements that we did not put in our composer.json. These are the packages that are required by a drupal/drupal package. For example, composer/installers package is actually responsible for placing our modules and themes into the Drupal's modules and themes folders, and not into vendor directory. Secondly, there is no repository specified in this composer.json, so the easiest solution on alpha so far is just to go to this folder with cd my_project/ and run composer config repositories.drupal composer https://packages.drupal.org/8once again.

Installing Modules and Themes

To install Drupal modules or themes for your site with composer, enter the following command at the root of your Drupal install:

composer require drupal/[name]

For example:

composer require drupal/token

Composer will then automatically update your composer.json file with a require statement of the format:

{
    "require": {
       "drupal/token": "1.0.x-dev"
    }
}

You can use either the project name, or the specific module name within a project when requiring modules. Composer will download the whole project that contains a particular module. For example, if you need the fe_block module from the features_extra project, you can either

composer require drupal/features_extra

Or use just the module name

composer require drupal/fe_block

It's better to be explicit by using the specific module name when you can. The beautiful thing is that the modules and themes will be placed into the folder where they have to be located according to Drupal.org's convention. Composer even creates the contrib folder within your sites/all/modules directory for Drupal 7.

Good to know

• Semantic Versioning Drupal.org contributed projects are currently not versioned with true Semantic Versioning. However, the Composer service on Drupal.org translates the Contrib project version schema, into a server format that Composer can understand. That means we need to be careful when specifying the versions of our packages and their dependencies in our composer.json - the versions are being translated, for example, from 7.x-3.4-beta2 to 3.4.0-beta2, from 7.x-1.x-dev to 1.0.x-dev and so on. The unstable releases will not be translated, and thus they are not available to composer. • Composer searchDrupal.org's composer endpoints for Drupal 7 and Drupal 8 both support the Composer search function - so you can also search for Drupal projects from the command line. The format for using Composer search is:

composer search pathauto

After executing this command you will see the list of packages that are available for you, and a short description of each of them. • Add composer.json to your modules A composer.json file can be added to your module to define the project itself. You may also define external dependencies for your module in composer.json. The wider PHP community uses Composer to manage packages; this is also done in Drupal. For example, the Drupal project has a dependency on the "drupal/core" package. The "drupal/core" package has a type defined as "drupal-core" so Composer knows what to do with it. The composer/installers library defines a number of Drupal types. These are

drupal-module
drupal-theme
drupal-library
drupal-profile
drupal-drush

As Drupal moves towards the wider PHP community, we may now include the composer.json to our modules and themes with the required definitions of name, description, and type of your project. Like this:

{
    "name": "drupal/better_module_dependencies",
    "description": "Makes module dependencies on a module settings page clickable.",
    "type": "drupal-module",
    "license": "GPL-2.0+"
}

• Namespace Collisions There might be namespace collisions between two modules in different Projects within a single composer.json. Projects themselves must have unique names, but the modules within projects do not have to be unique. Whenever a collision does occur, the most popular module will default to that namespace, and the other colliders will be given a new namespace of the format: project_modulename. For example: drupal/link_link for the link module.

More tools:

Despite the fact that we are only on alpha, there are already a lot of additional tools for managing our composer.json, connecting composer and drush and so on. Composer Manager provides the following functionality:

  • Discovers each module's composer.json file and adds it to the root composer.json merge list.
  • Adds the Drupal Packagist to the list of repositories, allowing Drupal modules to be required the same way as other packages.
  • The /admin/reports/composer-manager status report.

The Drupal 8 version of this module, however, is deprecated and no longer needed after Drupal 8.1 is out. But you can still use this module with Drupal 7. There is also a Composer module that allows using composer from Drush. It provides several drush commands: drush composer - Lists all available Composer commands; drush composer install - Parses composer.json, and installs all dependencies; drush composer update - Updates your dependencies to the latest version, and updates cached information; There are a plenty of other modules and libraries, that will more or less help you with integrating Drupal and Composer, it's not a big deal to find any of these. But it is really up to you to decide if you need them or not. Just remember that we are still on alpha and it is not recommended to use Composer in production environments. Though it is still definitely very useful for development.

You might also like