Chrome for Android fix.

Uncommon (Ab)Uses of Composer

Alain Schlesser
Software Engineer & WordPress Consultant

Introduction to Composer

  • The package manager for PHP

  • Manages dependencies of your project

  • Generates optimized autoloaders

  • Can fetch packages from diverse, de-centralized sources

  • Together with PHP-FIG initiative, has changed the PHP landscape

Composer's Role in a PHP Project

  • Centralized control over project lifecycle

  • Provides separate production and development paths

  • Makes projects self-contained


                $ git clone mycompany/project
                $ cd project
                $ composer install

Scripts vs Plugins

  • Two mechanisms for enhancing default Composer functionality

  • Use same hooks

    ( i.e. "post-install-cmd" <=> ScriptEvents::POST_INSTALL_CMD )

  • Overlap in multiple areas

Composer Scripts

  • Stored in project's composer.json file

  • Run on root package only

  • Intended for project automation

Composer Plugins

  • Stored in external package of type composer-plugin

  • Run on all included packages

  • Intended for Composer extension

Composer Script

          "name": "mycompany/package",
          "require-dev": {
            "phpunit/phpunit": "~6"
          "scripts": {
            "post-update-cmd": "@clearCache",
            "test": [
            "clearCache": "rm -rf cache/*"

Composer Plugin

              "name": "mycompany/composer-plugin",
              "type": "composer-plugin"
              "require": {
                "composer-plugin-api": "~1"
              "autoload": {
                "psr-4": {
                  "MyCompany\\ComposerPlugin\\": "src/"
              "extra": {
                "class": "MyCompany\\ComposerPlugin\\Plugin"

            <?php namespace MyCompany\ComposerPlugin;

            use Composer\EventDispatcher\EventSubscriberInterface;
            use Composer\Plugin\PluginInterface;
            use Composer\Script\Event;

            class Plugin implements PluginInterface,
              // Hook your code up to Composer events.
              public static function getSubscribedEvents()
                return array(
                  ScriptEvents::POST_INSTALL_CMD => 'doSomething',
                  ScriptEvents::POST_UPDATE_CMD  => 'doSomething',
              // Actually do something when triggered.
              public static function doSomething(Event $event) {}


Making modifications to external dependencies

Patching (1/2)


  • Needs upstream sync after every commit

  • Branch alias needed, but causes issues


  • Automatic upstream updates

  • Errors when it needs attention

  • Provides means for documentation

Tip: Get patches from GitHub by appending .diff to any commit URL

Patching (2/2)

Namespace Prefixing

Avoiding collisions between multiple conflicting versions of a same library

Namespace Prefixing (1/2)

  • Composer can only handle conflicts if it controls the entire project, starting from the root

  • In legacy systems like WordPress, individual plugins might want to use Composer, even though the Core does not use it

  • Prefixing allows multiple, potentially conflicting versions of a same library to co-exist in a project

Namespace Prefixing (2/2)

Keeping Data Up-to-date

Treating external data as just another dependency in the update flow

Keeping Data Up-to-date (1/2)

  • Treat external data as a managed dependency

  • Changes can be (version-)controlled

  • Makes data part of project's deployment flow

  • No need to remember manual updates


Example project:

Keeping Data Up-to-date (2/2)

Commit Hooks

Treating local commit hooks as development dependencies

Commit Hooks (1/3)

  • Treated as a development dependency

  • Immediately active after a composer install

  • Logic can be coded in PHP

  • Multiple, prioritisable scripts on same hook

Commit Hooks (2/3)

              "name": "mycompany/custom-hook",
              "type": "php-composter-action"
              "require": {
                "php-composter/php-composter": "*"
              "autoload": {
                "psr-4": {
                  "MyCompany\\CustomHook\\": "src/"
              "extra": {
                "php-composter-hooks": {

            <?php namespace MyCompany\CustomHook;

            use PHPComposter\PHPComposter\BaseAction;

            class MyAction implements BaseAction
               * Example pre-commit action method.
              public function preCommit()
                echo sprintf(
                  'Example Pre-Commit Hook %s @ %s' . PHP_EOL,

Commit Hooks (3/3)

Automating Boilerplate Code

Using a Composer package as a scaffold

Automating Boilerplate Code (1/2)

  • Use create-project for scaffolding:

    composer create-project <package> <dir>

  • Provide logic in PHP, hooked into Autoloader

  • Provide configuration in "extra" keys

  • Hook into post-create-project-cmd hook to trigger logic and to clean up after generation

            "name": "mycompany/boilerplate",
            "autoload": {
              "psr-4": {
                "Awesome\\Boilerplate\\Scripts\\": "_scripts/"
            "extra": {
              "mycompany-boilerplate": {
                "config-file": "_config/defaults.php",
            "scripts": {
              "post-create-project-cmd": [
                "rm -rf _scripts",
                "composer update --ansi",
                "phpunit --color=always"

Example project:

Automating Boilerplate Code (2/2)

Embedded Composer

Using Composer as a framework

Embedded Composer (1/2)

  • Provides access to all supported sources

  • Built-in event dispatching

  • Flexible scripting/plugin system still usable

Embedded Composer (2/2)

How will You abuse Composer?

Questions ?

I'm Alain Schlesser.

Follow me on Twitter:


Or visit my Personal Blog: