Using Composer with Drupal and DrushUsing Composer with Drupal and Drush Using Composer with Drupal and Drush Stanford DrupalCamp 10 April 2015 Greg Anderson + + =
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
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
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
Using Composer with Drupal and DrushUsing Composer with Drupal and Drush Installing Drupal 7 with Composer Can we do this? ?+ = 5
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
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
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.
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).
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
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
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!
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.
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" }, … }
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
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}/ " }, }, … }
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.
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
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
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!
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.
Using Composer with Drupal and DrushUsing Composer with Drupal and Drush How Do We Deploy Code? 22 rsyncinstallclone 1 2 3
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.
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
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
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
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
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.
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';
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
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

Using Composer with Drupal and Drush

  • 1.
    Using Composer withDrupal and DrushUsing Composer with Drupal and Drush Using Composer with Drupal and Drush Stanford DrupalCamp 10 April 2015 Greg Anderson + + =
  • 2.
    Using Composer withDrupal 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 withDrupal 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 withDrupal 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 withDrupal and DrushUsing Composer with Drupal and Drush Installing Drupal 7 with Composer Can we do this? ?+ = 5
  • 6.
    Using Composer withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal and DrushUsing Composer with Drupal and Drush How Do We Deploy Code? 22 rsyncinstallclone 1 2 3
  • 23.
    Using Composer withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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 withDrupal 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