Dependency Management for PHP

Presented by John Kelly

John Kelly

  • Software Engineering Lead at CDK Global
  • Zend Certified Engineer - PHP 5.3
  • Software engineering for 12 years

What is Composer?

  • Dependency manager for PHP
  • Manages per-project dependencies
  • Comes with built in autoloading and basic task-runner

What's wrong with PEAR?

  • Manages system-wide dependencies
  • Application doesn't manage dependencies
  • No autoloading provided

Installing Composer

http://getcomposer.org

OSX/Linux/Unix
Download composer.phar and move to /usr/local/bin/composer
Windows
Download Installed

Using Composer - Basics


# composer.json
{
    "require": {
        "silex/silex": "~1.1"
    }
}
                    
$ composer install

Using the package

Include the autoloader


require __DIR__ . '/vendor/autoload.php';
                    

Semantic Versioning

http://semver.org/

Definitions

MAJOR
When you make incompatible API changes
MINOR
When you add functionality in a backwards-compatible manner
PATCH
When you make backwards compatible bug fixes

Version Syntax

Exact version

1.0.2


# composer.json
{
    "require": {
        "silex/silex": "1.0.2"
    }
}
                            

Range

  • >=1.0
  • >=1.0,<2.0
  • >=1.0,<1.1 | >=1.2
  • 1.0 - 2.0 (hyphen)

# composer.json
{
    "require": {
        "silex/silex": ">=1.0,<1.1 || >=1.2"
    }
}
                        

Wildcard

  • 1.0.*
  • 1.*

# composer.json
{
    "require": {
        "silex/silex": "1.0.*"
    }
}
                        

Tilde Operator

  • ~1.2
  • ~1.2.1

# composer.json
{
    "require": {
        "silex/silex": "~1.2"
    }
}
                        

Caret Operator

  • ^1.2.3
  • ^1.2.0
  • ^1.2

# composer.json
{
    "require": {
        "silex/silex": "^1.2.3"
    }
}
                        

Test version constraints

http://semver.mwl.be/

Aliases

Used to alias a branch to a specific version.


# composer.json
{
    "require": {
        "silex/silex": "dev-master as 1.2.9"
    }
}
                    

Lock file

composer.lock

After installing the dependencies, Composer writes the list of the exact versions it installed into a composer.lock file. This locks the project to those specific versions.

Should I commit the lock file to VCS?

Depends...

Custom Installers

Allows for a package maintainer to customize the installation of their package.

PhpDocumentor Example


{
    "name": "phpdocumentor/template-responsive",
    "type": "phpdocumentor-template",
    "require": {
        "phpdocumentor/template-installer-plugin": "*"
    }
}

Custom Installers

PhpDocumentor Custom Installer Example


{
    "name": "phpdocumentor/template-installer-plugin",
    "type": "composer-plugin",
    "license": "MIT",
    "autoload": {
        "psr-0": {"phpDocumentor\\Composer": "src/"}
    },
    "extra": {
        "class": "phpDocumentor\\Composer\\TemplateInstallerPlugin"
    },
    "require": {
        "composer-plugin-api": "1.0.0"
    }
}

Custom Installers

PhpDocumentor Custom Installer Example


namespace phpDocumentor\Composer;

use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;

class TemplateInstallerPlugin implements PluginInterface
{
    public function activate(Composer $composer, IOInterface $io)
    {
        $installer = new TemplateInstaller($io, $composer);
        $composer->getInstallationManager()->addInstaller($installer);
    }
}

Custom Installers

PhpDocumentor Custom Installer Example


namespace phpDocumentor\Composer;

use Composer\Package\PackageInterface;
use Composer\Installer\LibraryInstaller;

class TemplateInstaller extends LibraryInstaller
{
    /**
    * {@inheritDoc}
    */
    public function getPackageBasePath(PackageInterface $package)
    {
        $prefix = substr($package->getPrettyName(), 0, 23);
        if ('phpdocumentor/template-' !== $prefix) {
            throw new \InvalidArgumentException(
                'Unable to install template, phpdocumentor templates '
                . 'should always start their package name with '
                . '"phpdocumentor/template-"'
            );
        }

        return 'data/templates/'.substr($package->getPrettyName(), 23);
    }

    /**
    * {@inheritDoc}
    */
    public function supports($packageType)
    {
        return 'phpdocumentor-template' === $packageType;
    }
}

Scripts

Execute custom code or package-specific commands during the composer execution process.

Private Packages

with Satis

Host your own composer repository.

https://github.com/composer/satis

Vendor binaries

Any command line script that a Composer package would like to pass along to a user who installs the package should be listed as a vendor binary.


# composer.json
{
    "bin": [
        "bin/my-script",
        "bin/my-other-script"
    ]
}
                    

DMS Considerations

Multiple PHP versions


# composer.json
{
    "config": {
        "platform": {
            "php": "5.3.3"
        }
    }
}
                        

Lets you fake platform packages (PHP and extensions) so that you can emulate a production env or define your target platform in the config

Build before deploy

$ composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction

THANK YOU

QUESTIONS?

BY John Kelly / john.m.kelly@cdk.com