composer tools & frameworks for drupal
TRANSCRIPT
COMPOSER TOOLS AND FRAMEWORKS FOR DRUPAL
+ =+
Greg Anderson and Doug Dobrzynski12 May 2015
COMPOSER DRUPAL DRUSH WIN
Pantheon.io / Prometsource.com 3
Why you should care about Composer
Today With Composer‣ Dependency Management Hell
‣ Manually include classes at runtime
‣ Large, unmanageable repository
‣ Composer manages dependencies
‣ Autoloader lazy-includes class files
‣ Repository remains clean and lean
Pantheon.io / Prometsource.com 4
Who Are We?
Greg Anderson Doug Dobrzynski
Open Source Contribution Engineer Build Manager / Drupal Developer
Pantheon.io / Prometsource.com 5
Agenda
‣ What is Composer?
‣ Installing Drupal 7 with Composer
• composer_vendor + custom-installer
• drupal-tangler
‣ Managing Your Project
‣ Installing Drupal 8 with Composer
WHAT IS COMPOSER?
PART ONE
Pantheon.io / Prometsource.com 7
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 GuzzleHttp\Client();
>=4,<6
guzzlehttp/guzzle
5.*
guzzlehttp/guzzle
v5.2.0
guzzlehttp/guzzle "autoload": { "psr-4": { "GuzzleHttp\\": "src/" } },
composer.json
Pantheon.io / Prometsource.com 8
Why Use Composer?
‣ Standard
‣ Easiest for developers • Dependency resolution
• Code updates
• Autoloading of classes
‣ Composer is being adopted everywhere
Pantheon.io / Prometsource.com 9
What Projects Are Using Composer?
Using Composer Not Using Composer
… and many others!
http/guzzle
fabpot/goutteDrupal Modules Drush Extensions
PHP APIssymfony/yaml
twig/twig
Not Using Composer
Pantheon.io / Prometsource.com 10
Drupal 7 and Composer
Can we do this?
?+ =
Pantheon.io / Prometsource.com 11
Composer Parts of the Whole
Composer
PHP dependency management
software.
Packagist
A software repository manager.
Custom Installer
An executable Composer
component. Optional.
autoload.php
A generated file that must be
included by your app.
composer.json
A structured file that defines a
project.
Pantheon.io / Prometsource.com 12
Repository Data for Drupal Projects
packagist.drupal-composer.org
A third-party repository containing data on projects from drupal.org.
Pantheon.io / Prometsource.com 13
Semantic Versioning
Drupal Module Version
7.x-1.5 DRUPAL-x.MODULE.MINOR
Versions are converted to semantic versioning before being published on packagist.drupal-composer.org.
7.1.5 MAJOR.MINOR.PATCH
Composer Version
Pantheon.io / Prometsource.com 14
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": "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.*", }, … }
composer.json
Repository and custom installers
(previously explained)
Drupal module that provides an autoload
strategy (next).
Drush Make
Pantheon.io / Prometsource.com 15
Autoloading in PHP
"autoload": { "psr-4": { "GuzzleHttp\\": "src/" }},
composer.json from guzzlehttp/guzzle
autoload_psr4.php generated by Composer via composer install
$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!
RUN TIME INSTALL TIME
<?phpinclude "vendor/autoload.php";
$client = new GuzzleHTTP\Client();
php source file that calls GuzzleHTTP
$map = require __DIR__ . '/autoload_psr4.php';foreach ($map as $namespace => $path) { $loader->setPsr4($namespace, $path);}
Composer autoloader registration called from vendor/autoload.php
include $vendorDir . '/guzzlehttp/guzzle/src/Client.php';
Pantheon.io / Prometsource.com 16
Custom Installers for Composer + D7
generalredneck/drupal-libraries-installer-plugin
promet/drupal-tangler
derhasi/composer-preserve-paths
davidbarratt/custom-installer
OR
OPTIONALnetresearch/composer-patches-plugin
Allows composer.json files to specify where components get installed.
Allows nested installation of composer libraries (e.g. Drupal modules inside of
Drupal core).
Installs modules and themes to their standard location in the vendor directory, and symlinks
to them from sites/all/modules/contrib or copies them to sites/all/modules/contrib.
Allows composer.json files to specify where components get installed.
Allows patch files to be applied to Drupal core or contrib modules after Composer installs
them.
Pantheon.io / Prometsource.com 17
Adding Composer Support
To make this work, we just need to include vendor/autoload.php
+ =
INSTALLING DRUPAL 7 WITH COMPOSER
PART TWO
Pantheon.io / Prometsource.com
Searches for composer.json files
in every module and dynamically
merges them.
19
Composer Options for Drupal 7
composer_autoload composer_manager
Fragile Complex
Searches for autoload.php files in every module
directory and loads them individually.
Pantheon.io / Prometsource.com
Writes a settings.php file that loads the correct autoload.php file.
Loads the sites/all/vendor/
autoload.php file.
20
Better Options for Drupal 7
composer_vendorpromet/drupal-tangler
Wins!Wins!
Pantheon.io / Prometsource.com 21
Directory Structure
mydrupalsite.org composer.json composer.lock htdocs sites default vendor -> vendor
all modules
vendor
We create a new top-level directory for our project, because Composer cannot manage dependencies in the same directory as composer.json.
We put our Drupal root directory in htdocs. Tangler defaults to www but allows the option to specify a different name.
With drupal-tangler
We put the vendor directory in root because that is the default location for the Composer installer.
We create a symlink to the vendor directory inside the document root to keep docroot self-contained.
Pantheon.io / Prometsource.com 22
Module and Profile Placement
mydrupalsite.org vendor
drupal views panopoly
htdocs profiles
panopoly -> panopoly sites all
modules contrib
views -> views
Each contributed module directory is symlinked to the corresponding directory in vendor.
With drupal-tangler
Each profile directory is symlinked to the corresponding directory in vendor.
Pantheon.io / Prometsource.com
mydrupalsite.org modules
custom my_feature_module
htdocssites
all modules
custom -> custom
23
Custom ModulesWith drupal-tangler
We put custom modules in the directory modules/custom. A symlink to this directory is placed in sites/all/modules so every module directory inside it will be found by Drupal.
Pantheon.io / Prometsource.com 24
Settings
mydrupalsite.org cnf
config.yml.distconfig.yml
htdocs sites default settings.php
We put default configuration for settings in config.yml.dist.
We put custom configuration for settings in config.yml.
The settings.php file is generated by settings_compile from config.yml. If config.yml does not exist, it is generated from config.yml.dist.
With drupal-tangler
Pantheon.io / Prometsource.com 25
Directory Structure
mydrupalsite.org
composer.json
composer.lock htdocs sites default settings.php files
all modules
vendor
We put the vendor directory in sites/all/vendor because that is where the composer_vendor project expects to find it.
Modules, themes and profiles are placed in their usual locations (e.g. sites/all/modules), not in the vendor directory.
With composer_vendor
The basic project layout is the same as in the drupal-tangler case.
Pantheon.io / Prometsource.com 26
Place the Vendor Directory
composer.json
{ "require": { … }, "config": { "vendor-dir": "htdocs/sites/all/vendor" }, … }
For composer_vendor with a custom-installer
Pantheon.io / Prometsource.com 27
Place Modules and Themes
{ "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
For composer_vendor with a custom-installer
Pantheon.io / Prometsource.com 28
Use Installation Profiles
{ "require": { "davidbarratt/custom-installer": "dev-master", "drupal/panopoly": "7.1.*", … }, "extra": { "custom-installer": { "drupal-profile": "htdocs/profiles/{$name}/" }, }, … }
composer_vendor composer.json
For composer_vendor with a custom-installer
Pantheon.io / Prometsource.com 29
Downloading 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
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.
Pantheon.io / Prometsource.com
Tangler works the same
30
Updating a Site
$ drush pm-update $ composer update $ drush updatedb
Composer
Remember - regardless of how you update your site, always do it on a copy first. Never update directly on the production site!
Drush
Pantheon.io / Prometsource.com 31
Install a Module from a Private Repository
{ "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
composer.json
For composer_vendor and drupal-tangler
Pantheon.io / Prometsource.com 32
Add a Patch to a Module
{ "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
composer.json
For composer_vendor and drupal-tangler
Pantheon.io / Prometsource.com 33
Use a Composer Library from a Module
1. Add a composer.json and require the library
2. There is no step two!
VERY IMPORTANT - Never try to include an autoload.php file from a plug-in; always leave autoloader management to the application.
Pantheon.io / Prometsource.com 34
Use Composer from a Drush Command
1. Add a composer.json and require the library
2. Call drush_autoload(__FILE__) from your hook_drush_init().
3. Require your Drush command in the composer.json of the Drupal site it is used in.
MANAGING YOUR PROJECT
PART THREE
Pantheon.io / Prometsource.com 36
Manage Project Code
drupal-tangler composer-vendormydrupalsite.org
.git
composer.json
composer.lock modules
htdocs
mydrupalsite.org .git composer.json composer.lock
htdocs sites
all modules custom contrib vendor
Commit composer.json and composer.lock to the repository.
Custom modules may be placed in the same repository.
Avoid committing composer-managed files.
Pantheon.io / Prometsource.com 37
Deploy Code Using ComposerLocal and Remote Dev Environments
install
clone
clone
1
2
3 4
install
Pantheon.io / Prometsource.com 38
Deploy Code Using RsyncCopy code from dev to stage or live
rsyncinstallclone1 2 3
Pantheon.io / Prometsource.com 39
Deploy Code Using Two RepositoriesIsolate the Provider’s Repository
clone
installclone
commit
rsyncpull
•
Deploy with git while maintaining a lean working repository by writing a short deploy script.
2 3
4
1
5
6
Pantheon.io / Prometsource.com 40
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
Pantheon.io / Prometsource.com 41
Creating a New Sitepromet/drupal7-framework
$ composer create-project promet/drupal7-framework project_name $ vagrant up --provision
=+ +
Pantheon.io / Prometsource.com 42
Creating a New Sitedrupal-composer/drupal-project
$ composer create-project drupal-composer/drupal-project:7.x-dev dir --stability dev --no-interaction # Set up settings.php, copy files… $ drush site-install
INSTALLING DRUPAL 8 WITH COMPOSER
PART FOUR
Pantheon.io / Prometsource.com 44
Installing Drupal 8 with Composer
Drupal 8 already uses Composer, so this should be easier, right?
?+ =
Pantheon.io / Prometsource.com 45
Why Doesn’t this work? “It’s complicated.”
How it is Supposed to Work
$ composer create-project drupal/drupal path ~8
Pantheon.io / Prometsource.com 46
Drupal 8 “Split core”"drupal/core" contains only the contents of the Drupal 8 core directory.
{ "require": { "composer/installers": "^1.0.20", "drupal/core": "8.0.x-dev", "drush/drush": “8.*”, }, "extra": { "installer-paths": { "htdocs/core": ["type:drupal-core"], "htdocs/modules/contrib/{$name}": ["type:drupal-module"] }, }, … } https://github.com/drupal-composer/drupal-project
Pantheon.io / Prometsource.com 47
More Information About Split Core
Using Subtree Splits to spread Drupal into everything
DAVID W BARRATT
Wednesday 13 May, 15:45 - 16:45
ROOM 511BC - Pantheon
Pantheon.io / Prometsource.com 48
Drupal 8 Project Layout with Drush and Composer
mydrupalsite.org
composer.json
vendor drush
drush drush
htdocs sites core
modules autoload.php index.php .htaccess
We place the vendor directory in its standard location in the project directory, not in the core directory where D8 has it.
We need to modify Drupal’s autoload.php file to include the autoloader in our vendor directory.
Copy all of the other regular files from the Drupal 8 root directory.
Composer will place drush inside the vendor directory, which probably is not in your $PATH.
Pantheon.io / Prometsource.com
W
49
Options to Run Site-Local Drush
Put $HOME/.drush/use/bin in your $PATH Source example.bashrc Redispatch
$ drush site-set @site $ drush status
$ drush use @site (@site) $ drush status $ drush @site status
Works today!Under discussion in Drush issue queue:https://github.com/drush-ops/drush/pull/1343
Pantheon.io / Prometsource.com 50
Modified autoload.php
autoload.php in Drupal 8 root directory
<?php
return require __DIR__ . '/../vendor/autoload.php';
<?php
return require __DIR__ . '/core/vendor/autoload.php';
autoload.php in our modified site
Pantheon.io / Prometsource.com 51
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.
Pantheon.io / Prometsource.com 52
Where Do We Go From Here?
https://groups.drupal.org/composer
http://drupal-composer.org/
https://github.com/drupal-composer
https://getcomposer.org/
@greg_1_anderson
@dsdobrzynski
https://github.com/promet/drupal7-framework