Pantheon's Greg Anderson presents on the topic of using Composer with Drupal and Drush. Composer is a dependency manager that has become the de-facto standard for managing the components used in any sort of PHP library or application. Drupal is no exception to this, and in this presentation, Greg showed that the future is already here: it is completely possible to use native Composer functions to manage the modules and themes used in a Drupal site. In this capacity, Composer can take over the functions usually performed with drush make, drush pm-download, and drush pm-update.
1. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Using Composer
with Drupal and Drush
Stanford DrupalCamp 10 April 2015
Greg Anderson
+ + =
2. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
What Is Composer?
An Installer A Dependency Manager An Autoloader
{
"require": {
"php": ">=5.4.0",
"symfony/browser-kit": "~2.1",
"symfony/css-selector": "~2.1",
"symfony/dom-crawler": "~2.1",
"guzzlehttp/guzzle": ">=4,<6"
},
âŠ
}
Evaluate and select <?php
$client = new GuzzleHttpClient();
2
>=4,<6
guzzlehttp/guzzle
5.*
guzzlehttp/guzzle
v5.2.0
guzzlehttp/guzzle
"autoload": {
"psr-4": {
"GuzzleHttp": "src/"
}
},
composer.json
3. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Why Use Composer?
3
1. Standard
2. Easiest for developers
a. Dependency resolution
b. Code updates
c. Autoloading of classes
3. Composer is being adopted everywhere
4. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Using
Composer
Not Using
Composer
What Projects Are Using Composer?
4
⊠and many others!
http/guzzle
fabpot/goutteDrupal Modules Drush Extensions
PHP APIs
symfony/yaml
twig/twig
5. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Installing Drupal 7 with Composer
Can we do this?
?+ =
5
6. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Composer Parts of the Whole
Composer Packagist composer.json Custom Installer
PHP dependency
management
software.
A software
repository
manager.
A structured file
that defines a
project.
An executable
Composer
component.
Optional.
6
7. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Parts Needed for Composer + D7
packagist.drupal-composer.org davidbarratt/custom-installer derhasi/composer-preserve-paths
A third-party
repository containing
data on projects from
drupal.org.
Allows composer.json
files to specify where
components get
installed.
Allows nested
installation of
composer libraries
(e.g. Drupal modules
inside of Drupal core).
7
8. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Semantic Versioning
Drupal Module Version Composer Version
8
7.x-1.5
DRUPAL-x.MODULE.MINOR
7.1.5
MAJOR.MINOR.PATCH
â Versions are converted to semantic versioning before being
published on packagist.drupal-composer.org.
9. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Comparison with Drush Make
; Drush make file that uses guzzle
; API
api = 2
; Core
core = 7.x
; Drupal project.
projects[drupal][type] = core
projects[drupal][version] = 7.x
projects[drupal][download][type] = git
projects[drupal][download][branch] = 7.x
; Modules
projects[] = composer_manager
projects[] = aws_glacier
projects[] = devel
{
"name": "organization/project",
"description": "Example Drupal composer.json file",
"repositories": [
{
"type": "composer",
"url": "http://packagist.drupal-composer.org/ "
}
],
"require": {
"davidbarratt/custom-installer": "dev-master",
"derhasi/composer-preserve-paths": "0.1.*",
"drupal/drupal": "7.*",
"drupal/composer_vendor": "7.1.*",
"http/guzzle": "~5",
"drupal/devel": "7.1.*",
},
"config": {
"vendor-dir": "htdocs/sites/all/vendor"
},
"extra": {
âŠ
},
"minimum-stability": "dev",
"prefer-stable": true
}
Drush Make composer.json
9
Repository
and custom
installers, as
previously
explained.
Drupal module
that provides
an autoload
strategy
(next).
10. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Autoloading in PHP
10
<?php
$client = new GuzzleHttpClient();
"autoload": {
"psr-4": {
"GuzzleHttp": "src/"
}
},
composer.json from guzzlehttp/guzzle
autoload_psr4.php
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
Registers its own autoload class when vendor/autoload.
php is included.
$vendorDir = dirname(dirname(__FILE__));
return array(
'GuzzleHttp' => array($vendorDir . '/guzzlehttp/guzzle/src'),
);
Saves one line of code per class - but itâs a very important line!
Generates class maps when composer install is run
11. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Adding Composer Support
To make this work, we just need to include
vendor/autoload.php
+ =
11
12. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Composer Modules for Drupal 7
composer_autoload composer_manager composer_vendor
Searches for
autoload.php files
in every module
directory and loads
them individually.
Searches for
composer.json files
in every module and
dynamically merges
them.
Loads the
autoload.php file in
sites/all/vendor.
12
Fragile Complex
Wins!
13. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Directory Structure with D7 + Composer
â mydrupalsite.org
â composer.json
â composer.lock
â htdocs
â sites
â default
â settings.php
â files
â all
â modules
â vendor
13
We create a new top-level directory
for our project, because composer
cannot manage dependencies in
the same directory as composer.json.
We put the vendor directory in
sites/all/vendor because that is
where the composer_vendor project
expects to find it.
We will put our Drupal root directory in
htdocs.
14. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
How Do We Place the Vendor Directory?
composer.json
14
{
"require": {
âŠ
},
"config": {
"vendor-dir": "htdocs/sites/all/vendor"
},
âŠ
}
15. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
How Do We Place Modules and Themes?
15
{
"require": {
"davidbarratt/custom-installer": "dev-master",
âŠ
},
"extra": {
"custom-installer": {
"drupal-module": "htdocs/sites/all/modules/contrib/{$name}/",
"drupal-theme": "htdocs/sites/all/themes/contrib/{$name}/"
},
},
âŠ
}
composer.json
16. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Can We Use Installation Profiles?
composer.json
16
{
"require": {
"davidbarratt/custom-installer ": "dev-master",
"drupal/panopoly ": "7.1.*",
âŠ
},
"extra": {
"custom-installer": {
"drupal-profile": " htdocs/profiles/{$name}/ "
},
},
âŠ
}
17. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
How Do We Download Modules?
$ drush dl devel
Project devel (7.x-1.5) downloaded
to sites/all/modules/contrib/devel.
Project devel contains 3 modules:
devel_generate, devel,
devel_node_access.
$ composer require drupal/devel '7.*'
./composer.json has been updated
Loading composer repositories with
package information
Updating dependencies (including
require-dev)
Drush Composer
17
â Drush will select the right module major version, but
composer require must be told which version to use.
â Composer require will update the composer.json file
before installing the module.
18. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Install a Module from a Private Repository
18
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/your-org/your-module"
}
],
"require": {
"your-org/your-module": "dev-master"
},
âŠ
} https://knpuniversity.com/screencast/question-answer-day/create-composer-package
19. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Add a Patch to a Module
19
{
"require": {
"netresearch/composer-patches-plugin": "~1.0"
},
"extra": {
"patches": {
"drupal/features": {
"7.2.2":[
{
"title": "Remove mtime from .info export (added by Drupal 7.33)",
"url": "https://www.drupal.org/files/issues/2381739-features-mtime.patch"
}
]
}
}
},
âŠ
}
http://cambrico.net/drupal/using-composer-to-build-your-drupal-7-projects
20. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
How Do We Update a Site?
$ drush pm-update $ composer update
$ drush updatedb
Drush Composer
20
Remember - regardless of how you update your site,
always do it on a copy first. Never update directly on the
production site!
21. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
How Do We Manage Project Code?
â mydrupalsite.org
â .git
â composer.json
â composer.lock
â .gitignore
â htdocs
â sites
â all
â modules
â custom
â contrib
â vendor
21
Commit composer.json. and
composer.lock to the repository.
composer.lock only changes when
you run composer update.
Avoid committing composer-managed
directories, such as
sites/all/modules/contrib and
sites/all/vendor.
If you have custom modules, you can
commit them in the custom directory.
22. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
How Do We Deploy Code?
22
rsyncinstallclone
1 2 3
23. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Idea - Using Two Repositories
23
clone
installclone
commit
rsync pull
2 3
1
4
5
6
Deploy with git while
maintaining a lean working
repository by writing a short
deploy script.
24. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Converting an Existing Site
$ drush dl composer_generate
$ drush @site composer-generate > composer.json
$ composer install
# Set up settings.php, copy filesâŠ
$ drush site-install
24
25. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Installing Drupal 8 with Composer
Drupal 8 already uses Composer, so
this should be easier, right?
?+ =
25
26. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
How it is Supposed to Work
26
Why Doesnât this work? âItâs complicated.â
$ composer create-project drupal/drupal path ~8
27. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Template composer.json File for Drupal 8
Utilize a custom installer to set install locations
27
{
"require": {
"composer/installers": "^1.0.20",
"drupal/core": "8.0.x-dev",
"drush/drush": "~7",
},
"extra": {
"installer-paths": {
"web/core": ["type:drupal-core"],
"web/modules/contrib/{$name}": ["type:drupal-module"]
},
},
âŠ
}
drupal/core contains only
the contents of the Drupal 8
core directory. This is called a
âsplit coreâ.
https://github.com/webflo/drupal-site-template
28. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Setting Up Drupal 8 for Composer
â mydrupalsite.org
â composer.json
â vendor
â htdocs
â sites
â modules
â themes
â autoload.php
â index.php
â .htaccess
28
We place the vendor directory in its
standard location in the project
directory, rather than in the core
directory where Drupal 8 expects it.
Copy all of the other regular files from
the Drupal 8 root directory.
We need to modify Drupalâs autoload.
php file to include the autoloader in our
vendor directory.
29. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Modified autoload.php
autoload.php in our modified site
autoload.php in Drupal 8 root
directory
29
<?php
return require __DIR__ . '/../vendor/autoload.php';
<?php
return require __DIR__ . '/core/vendor/autoload.php';
30. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
What Does âHacking Coreâ Mean?
âEvery time you hack coreâŠâ by Greg Dunlap (heyrocker) DrupalCon Szeged 2008
If you have to
resolve merge
conflicts when
you update, then
you are hacking
core.
30
31. Using Composer with Drupal and DrushUsing Composer with Drupal and Drush
Where Do We Go From Here?
31
https://groups.drupal.org/composer
http://drupal-composer.org/
https://github.com/drupal-composer
https://getcomposer.org/
@greg_1_anderson