Upload
jason-grimes
View
1.617
Download
4
Embed Size (px)
Citation preview
Dependency management with
Composer
Jason Grimes / @jason_grimes / [email protected]
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
$ 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": "[email protected]"}
],
"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.
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 / [email protected]