• David Duymelinck

  • Software Engineer

If you ever attended a PHP conference in the last years, you know Composer is the standard tool to manage your dependencies. Many PHP projects, like Symfony and Drupal 8, come with an out-of-the-box composer.json file. Though it may feel like a no-brainer to use dependency management for third party libraries, have you looked at what else Composer can do for your build automation and continuous integration in PHP? 

Better dependency management

If you have worked on a Drupal 7 or 8 project in which the modules are manually added and enabled, you know what a pain it can be to get the same application behaviour between different developers or environments. This is why the drupal/search_api module is added as a dependency in the “require”-section of the composer.json file below.

"require": {
   "php": ">=5.6.0",
   "composer/installers": "1.2.0",
   "wikimedia/composer-merge-plugin": "1.4.0",
   "drush/drush": "8.1.11",
   "drupal/search_api": "1.1.0"
},
"replace": {
   "drupal/core": "8.3.2"
},

The first modification is the addition of the PHP version. It is important to know that Drupal 8, at the time of writing, supports PHP 5.5.9. But support for this PHP version ended in 2016, so it is a good idea to require a higher PHP version for your Drupal project.

The second modification is to set the dependencies to a specific version. This is to prevent errors that could occur should a version of a library unexpectedly break backwards compatibility.

The last modification is already mentioned, the addition of the Drupal module, drupal/search_api. This is possible because the Composer plugin, composer/installers, is added as a dependency. This handy Composer plugin recognizes the type key in third party libraries or, in this case, a Drupal module (i.e. a composer.json file). Based on that key, the plugin will figure out in which directory the dependency should be installed.

Another dependency that has been added is Drush. This is a CLI tool that mirrors the Drupal maintenance/configuration backend pages. Drush is one of the key players in how Composer can be used to automate the build and deployment flow.

Easier integration with different build servers

For our continuous integration and deployment we use Bamboo. Bamboo allows us to define tasks that should happen when the project is build or when it deploys. Here’s an example of a deploy task for the test server:

composer install
composer run site-install-dev
composer run enable-module

The Composer commands that start with composer run can be found in the “scripts”-section of the composer.json file, which is shown below:

"scripts": {
   // ...
   "refresh-drush": "./vendor/bin/drush cc drush",
   "site-install-dev": [
       "@refresh-drush",
       "./vendor/bin/drush build-check-usage --runOn=dev,test",
       "./vendor/bin/drush @dev site-install -y dev"
   ],
   "enable-modules": [
       "./vendor/bin/drush en search_api -y"
   ]
}

The main benefit of adding the Drush commands as Composer commands is abstraction. If you want to change from Drush to Drupal Console, you can do so without changing the build and deploy plans by altering the above composer.json to point to the new commands.

The one disadvantage of composer run commands is that they can run on every environment as long as the dependencies are defined for that environment. This is why there is a custom Drush command, build-check-usage, that can check on which environment the enclosing Composer command can run.

function drush_build_check_usage() {
 $runOn = drush_get_option('runOn');
   $allowed = !empty($runOn) ? explode(',', $runOn) : [];
 if(empty($allowed)) {
   return drush_set_error(dt("The command can not run."));
 }

 if(!in_array(getenv('PROJECT_ENV'), $allowed)) {
   return drush_set_error(dt('The command can not run in this environment.'));
 }
}

The main thing to notice in the above code is the use of the environment variable PROJECT_ENV. This is used to determine on which environment the application is running, on production or on one of the pre-production environments, during the build or deployment flow. The PROJECT_ENV variable should not have an effect on your application. That is the task of environment variables for database connection settings, API authentication, and so on.

Conclusion

As you can see, you don’t need a lot of modifications to start using Composer as a tool for your build automation and development flow. Of course you still need more automation, like running tests and database migrations, to create a really smooth flow for you and your fellow developers.

Composer is the tool that can help your PHP project from beginning to end. It starts by making it easy to get dependencies. After that, Composer helps you by setting up the project on different environments. And when all changes are checked and approved, it will help you to ship your project to the public.