Using Composer with Drupal and Drush

31
Using Composer with Drupal and Drush Using Composer with Drupal and Drush Using Composer with Drupal and Drush Stanford DrupalCamp 10 April 2015 Greg Anderson + + =

Transcript of Using Composer with Drupal and Drush

Page 1: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

Using Composerwith Drupal and Drush

Stanford DrupalCamp 10 April 2015

Greg Anderson

+ + =

Page 2: Using Composer with Drupal and Drush

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 GuzzleHttp\Client();

2

>=4,<6

guzzlehttp/guzzle

5.*

guzzlehttp/guzzle

v5.2.0

guzzlehttp/guzzle

"autoload": { "psr-4": { "GuzzleHttp\\": "src/" } },

composer.json

Page 3: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

Why Use Composer?

3

1. Standard

2. Easiest for developersa. Dependency resolutionb. Code updatesc. Autoloading of classes

3. Composer is being adopted everywhere

Page 4: Using Composer with Drupal and Drush

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

Page 5: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

Installing Drupal 7 with Composer

Can we do this?

?+ =

5

Page 6: Using Composer with Drupal and Drush

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

Page 7: Using Composer with Drupal and Drush

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

Page 8: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

Semantic Versioning

Drupal Module Version Composer Version

8

7.x-1.5DRUPAL-x.MODULE.MINOR

7.1.5MAJOR.MINOR.PATCH

● Versions are converted to semantic versioning before being published on packagist.drupal-composer.org.

Page 9: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

Comparison with Drush Make; Drush make file that uses guzzle; APIapi = 2

; Corecore = 7.x

; Drupal project.projects[drupal][type] = coreprojects[drupal][version] = 7.xprojects[drupal][download][type] = gitprojects[drupal][download][branch] = 7.x

; Modulesprojects[] = composer_managerprojects[] = aws_glacierprojects[] = 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).

Page 10: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

Autoloading in PHP

10

<?php

$client = new GuzzleHttp\Client();

"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

Page 11: Using Composer with Drupal and Drush

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

Page 12: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

Composer Modules for Drupal 7Composer Modules for Drupal 7Composer Modules for Drupal 7composer_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 ComplexWins!

Page 13: Using Composer with Drupal and Drush

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 directoryfor our project, because composercannot manage dependencies inthe 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.

Page 14: Using Composer with Drupal and Drush

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" }, … }

Page 15: Using Composer with Drupal and Drush

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

Page 16: Using Composer with Drupal and Drush

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}/ " }, }, … }

Page 17: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

How Do We Download Modules?$ drush dl develProject 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 updatedLoading composer repositories with package informationUpdating 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.

Page 18: Using Composer with Drupal and Drush

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

Page 19: Using Composer with Drupal and Drush

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

Page 20: Using Composer with Drupal and Drush

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!

Page 21: Using Composer with Drupal and Drush

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.

Page 22: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

How Do We Deploy Code?

22

rsyncinstallclone

1 2 3

Page 23: Using Composer with Drupal and Drush

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.

Page 24: Using Composer with Drupal and Drush

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

Page 25: Using Composer with Drupal and Drush

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

Page 26: Using Composer with Drupal and Drush

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

Page 27: Using Composer with Drupal and Drush

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

Page 28: Using Composer with Drupal and Drush

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.

Page 29: Using Composer with Drupal and Drush

Using Composer with Drupal and DrushUsing Composer with Drupal and Drush

Modified autoload.phpautoload.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';

Page 30: Using Composer with Drupal and Drush

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

Page 31: Using Composer with Drupal and Drush

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