Dependency management with Composer

Post on 06-May-2015

1.619 views 4 download

Transcript of Dependency management with Composer

Dependency management with

Composer

Jason Grimes / @jason_grimes / jason@grimesit.com

Triangle PHP - June 2013

Composer is a

dependency manager for

PHP.

Like npm in Node,

or bundler in Ruby.

What are dependencies?

Third-party libraries

or other assets your project depends on

which are stored in a separate repository

from your project sources.

• Define dependencies in a version controlled config file.

• Download & install them all with one command.

• Have identical versions in all project environments.

• Automate this part of your build process.

A dependency manager lets you:

ComposerPEAR• Per-project

• Open inclusion

• Central repository

• System-wide

• Strict control

• Dispersed channels

vs

Composer is becoming the de-facto standard

Installing Composer:

$ curl -sS https://getcomposer.org/installer | php

$ sudo mv composer.phar /usr/local/bin/composer

Keeping Composer up to date periodically:

$ sudo composer self-update

Updating to version d498e73363f8dae5b9984bf84ff2a2ca27240925.

Downloading: 100%

Two main use cases:

• Managing dependencies in a project

• Distributing a library

Managing dependencies in a project

Getting a dependency:

{

"require": {

"silex/silex": "~1.0"

}

}

$ cd ~/myproject

$ vim composer.json

$ composer install

$ composer install

Loading composer repositories with package informationInstalling dependencies (including require-dev)

- Installing psr/log (1.0.0) Loading from cache

- Installing symfony/routing (v2.3.0) Loading from cache

- Installing symfony/debug (v2.3.1) Downloading: 100%

- Installing symfony/http-foundation (v2.3.1) Downloading: 100%

- Installing symfony/event-dispatcher (v2.3.0) Loading from cache

- Installing symfony/http-kernel (v2.3.0) Loading from cache

- Installing pimple/pimple (v1.0.2) Loading from cache

- Installing silex/silex (v1.0.0) Loading from cache

symfony/routing suggests installing symfony/config ()

...

Writing lock fileGenerating autoload files

Packages are installedin the vendor/ subdirectory

$ ls vendor

autoload.phpcomposer/pimple/psr/silex/symfony/

Specifying versions

"~1.2"

">=1.2,<2.0"

"1.2.*"

"1.2.3"

Recommended. “Up to next significant release.” (semver)

Only stable packages are installed by default.

Get a non-stable version like this:{

"require": {

"silex/silex": "~1.0@dev"

},

}

Stability flags, in order of priority: dev, alpha, beta, RC, and stable.

To get the latest commit from the master branch:{

"require": {

"silex/silex": "dev-master"

},

}

Ensuring identical versionsin all project environments

• composer.json - the config file. Specifies versions as flexible patterns.

• composer.lock - the lock file. Automatically written by composer.Lists the exact versions that were installed.

Both files should be stored in version control.

Two important files:

• composer install - Install dependencies, using the versions listed in composer.lock.

• composer update - Determine the latest allowed versions, install them, and write the version numbers to composer.lock.

Two important commands:

You can specify which packages to update,leaving the others untouched:

$ composer update monolog/monolog

This can be useful when adding a new dependency.

composer update might break things. Only run it in dev environments.

Commit composer.lock to version control when you’re ready to deploy the new versions.

Remember:

composer install ensures you have the exact same versions as everyone else using that composer.lock file.

Run composer install in your build scripts.

Autoloading

Composer sets up autoloading of your dependencies (for free).

Just include vendor/autoload.php:

<?php

require ‘vendor/autoload.php’;

$app = new Silex\Application();

You can also use composer to configure autoloading for your own code.

{

"require": {...},

"autoload": {

"psr-0": {"MyApp": "src/"}

},

}

<?php

require ‘vendor/autoload.php’;

$app = new MyApp\Foo(); // From src/MyApp/Foo.php

composer.json

Various autoloading conventions are supported.

"autoload": {

"psr-0": {

"MyApp\\Test": "src/test",

"MyApp_": "src",

"": "src/"

},

"classmap": ["src/", "lib/", "Something.php"],

"files": ["src/MyLibrary/functions.php"]

},

MyApp\Test\FooTest => src/test/MyApp/Test/FooTest.php MyApp_Foo => src/MyApp/Foo.php Foo => src/Foo.php

Search for classes in *.php and *.inc files in these locations, and generate a key/value array mapping class names to files.

Explicitly load these files on every request.

You can generate the autoload files without running an install or update:

$ composer dump-autoload

In production, you can generate a class map for all classes, to optimize performance:

$ composer dump-autoload --optimize

Finding packages

https://packagist.org

$ composer search oauth2 server

adoy/oauth2 Light PHP wrapper for the OAuth 2.0 protocol (based on OAuth 2.0 Authorization Protocol draft-ietf-oauth-v2-15)

drahak/oauth2 Nette OAuth2 Provider bundle

opauth/oauth2 Base OAuth2 strategy for Opauth

zircote/oauth2 OAuth2 Library, this is by no means complete nor is the test coverage optimal, mileage may (will) vary.

friendsofsymfony/oauth2-php OAuth2 library

bshaffer/oauth2-server-php OAuth2 Server for PHP

league/oauth2-server A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.

...

$ composer show league/oauth2-server

name : league/oauth2-serverdescrip. : A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.keywords : authorization, api, Authentication, oauth, oauth2, server, resourceversions : dev-master, 2.1.1, 2.1, 2.0.5, 2.0.4, 2.0.3, 2.0.2, 2.0, 1.0.8, 1.0.7, 1.0.6, 1.0.5, 1.0.4, 1.0.3, 1.0.2, 1.0.1, 1.0.0, 0.4.2, 0.4.1, 0.4, 0.3.5, 0.3.4, 0.3.3, 0.3.2, 0.3.1, 0.3, 0.2.3, 0.2.2, 0.2.1, 0.2, dev-develop, dev-temptype : librarylicense : MITsource : [git] https://github.com/php-loep/oauth2-server.git 2.1.1dist : [zip] https://api.github.com/repos/php-loep/oauth2-server/zipball/2.1.1 2.1.1names : league/oauth2-server, lncd/oauth2, league/oauth2server

autoloadpsr-0League\OAuth2\Server => src/

requiresphp >=5.3.0

requires (dev)mockery/mockery >=0.7.2

suggestszetacomponents/database Allows use of the build in PDO storage classes

replaceslncd/oauth2 *league/oauth2server *

Bootstrapping a project

$ composer create-project fabpot/silex-skeleton ~/myproject

create-project clones a project skeleton and installs its dependencies.

$ composer create-project fabpot/silex-skeleton ~/myproject

Installing fabpot/silex-skeleton (v1.0.0) - Installing fabpot/silex-skeleton (v1.0.0) Downloading: 100%

Created project in /home/vagrant/myprojectLoading composer repositories with package informationInstalling dependencies (including require-dev)

- Installing psr/log (1.0.0) Loading from cache

- Installing twig/twig (v1.13.1) Downloading: 100%

- Installing symfony/icu (v1.2.0) Downloading: 100%

- Installing symfony/intl (v2.3.1) Downloading: 100%...

symfony/twig-bridge suggests installing symfony/templating ()

...

Writing lock fileGenerating autoload files

$ ls ~/myproject

cache/composer.jsoncomposer.lockconfig/consolelogs/src/templates/vendor/web/

Adding another dependency from the command line

$ composer require doctrine/dbal:~2.3

composer.json has been updatedLoading composer repositories with package informationUpdating dependencies (including require-dev)

- Installing doctrine/common (2.3.0) Loading from cache

- Installing doctrine/dbal (2.3.4) Loading from cache

Writing lock fileGenerating autoload files

Distributing a library

Any directory with a composer.json fileis a package.

To be installable, a package just needs a name:

{

"name": "myvendorname/my-package",

"require": {...}

}

Recommended info for composer.json{

"name": "jasongrimes/silex-simpleuser",

"description": "A simple db-backed user provider for Silex.",

"keywords": ["silex", "user", "user provider"],

"homepage": "http://github.com/jasongrimes/silex-simpleuser",

"license": "MIT",

"authors": [

{"name": "Jason Grimes", "email": "jason@grimesit.com"}

],

"require": { ... },

"autoload": {

"psr-0": {"JG\SimpleUser": "src/"}

},

"suggest": {

"monolog/monolog": "Allows more advanced logging."

}

}

Specify versions with tags in your VCS.

Tags should match X.Y.Z or vX.Y.Z with optional RC, beta, alpha or patch suffix.

1.0.0v1.0.01.10.5-RC1v4.4.4beta2v2.0.0-alphav2.0.4-p1

“dev” versions are created automatically for every branch

Branch names that look like versionsbecome {branch}-dev:

2.0 => 2.0.x-dev1.2.x => 1.2.x-dev

Other branch names become dev-{branch}:

master => dev-masterbugfix => dev-bugfix

Specifying system requirements

{

"require": {

...

"php": ">=5.3",

"ext-PDO": “~1.0@dev”,

"lib-openssl": "openssl"

}

}

Run composer show --platform for a list of locally available platform packages.

Executing scripts with Composer

{

"scripts": {

"post-update-cmd": "MyVendor\\MyClass::postUpdate",

"post-package-install": [

"MyVendor\\MyClass::postPackageInstall"

],

"post-install-cmd": [

"MyVendor\\MyClass::warmCache",

"phpunit -c app/"

]

}

}

composer.json

Many other pre- and post- event hooks are supported.

Submitting to Packagist

https://packagist.org

If using github, add a service hook

Packagist will update whenever you push, instead of being crawled only once daily.

https://github.org

Custom repositories

Maintaining your own forks

When you fix a bug in a third-party library, use your own fork until your fix gets accepted upstream.

{

"repositories": [

{

"type": "vcs",

"url": “https://github.com/jasongrimes/monolog”,

}

],

"require": {

"monolog/monolog": "dev-bugfix"

}

}

Your fork

Branch with your fix

Custom repos have priority over packagist, so your fork gets used instead of the original.

PEAR packages

{ "repositories": [ { "type": "pear", "url": "http://pear2.php.net" } ], "require": { "pear-pear2.php.net/PEAR2_Text_Markdown": "*", "pear-pear2/PEAR2_HTTP_Request": "*" }}

Non-composer packages

{ "repositories": [ { "type": "package", "package": { "name": "smarty/smarty", "version": "3.1.7", "dist": { "url": "http://smarty.net/Smarty-3.1.7.zip", "type": "zip" }, "source": { "url": "http://smarty-php.googlecode.com/svn/", "type": "svn", "reference": "tags/Smarty_3_1_7/distribution/" }, "autoload": { "classmap": ["libs/"] } } } ], "require": { "smarty/smarty": "3.1.*" }}

Private repositories

Use Satis to generate private Composer repositories.

$ composer create-project composer/satis --stability=dev

$ vim config.json

{

"repositories": [

{ "type": "vcs", "url": "http://github.com/mycompany/privaterepo" },

{ "type": "vcs", "url": "http://svn.example.org/private/repo" },

{ "type": "vcs", "url": "http://github.com/mycompany/privaterepo2" }

],

"require": {

"company/package": "*",

"company/package2": "*",

"company/package3": "2.0.0"

}

}

$ php bin/satis build config.json web/

Builds static repo in web/

Use your private repo like any other:

{

"repositories": [ {

"type": "composer",

"url": "http://packages.example.org/"

} ],

"require": {

"company/package": "1.2.0",

"company/package2": "1.5.2",

"company/package3": "dev-master"

}

}

In conclusion...

• ...install dependencies not stored in your project’s VCS repo.

• ...ensure identical versions in all your project’s environments.

• ...handle autoloading.

• ...distribute your open source libraries.

• ...manage your private repositories.

Use Composer to:

Resources

• http://getcomposer.org

• https://packagist.org/

• #composer on freenode

Jason Grimes / @jason_grimes / jason@grimesit.com