– Dependency Management for PHP – What's wrong with PEAR?



– Dependency Management for PHP – What's wrong with PEAR?

0 0


ComposerSlides

Composer slides used in a talk by John Kelly on 9/2/2014 at PDX-PHP meetup.

On Github PHPDX / ComposerSlides

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"
    }
}
This will tell Composer to install this version and this version only. If other dependencies require a different version, the solver will ultimately fail and abort any install or update procedures.

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"
    }
}
By using comparison operators you can specify ranges of valid versions. Valid operators are >, >=, <, <=, !=. You can define multiple ranges. Ranges separated by a space ( ) or comma (,) will be treated as a logical AND. A double pipe (||) will be treated as a logical OR. AND has higher precedence than OR.

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"
    }
}
Next significant release. Specifies a minimum version, but allows the last digit specified to go up.

Caret Operator

  • ^1.2.3
  • ^1.2.0
  • ^1.2
# composer.json
{
    "require": {
        "silex/silex": "^1.2.3"
    }
}
Next significant release. For pre-1.0 versions it also acts with safety in mind and treats ^0.3 as >=0.3.0 <0.4.0. This is the recommended operator for maximum interoperability when writing library code.

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...

This can help your team to always test against the same dependency versions. However, this lock file will not have any effect on other projects that depend on it. It only has an effect on the main project.

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": "*"
    }
}
such as installing packages outside of the default vendor library. In these cases you could consider creating a Custom Installer to handle your specific logic. phpDocumentor features Templates that need to be installed outside of the default /vendor folder structure. As such they have chosen to adopt the phpdocumentor-template type and create a plugin providing the Custom Installer to send these templates to the correct folder.

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);
    }
}
alter or expand Composer's functionality with your own

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.

This is just the task-runner side of Composer. Like Gradle, Maven, Grunt, Gulp.

Private Packages

with Satis

Host your own composer repository.

https://github.com/composer/satis

For example let's assume you have a few packages you want to reuse across your company but don't really want to open-source. You would first define a Satis configuration: a json file with an arbitrary name that lists your curated repositories.

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"
    ]
}
Creates a .BAT and Bash file for you, in a known location.

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

Dependency Management for PHP Presented by John Kelly