Jordi Boggiano
@seldaek


Composer Best Practices

Building the internet for over 10 years
 http://seld.be

Symfony, Composer and other OSS contributions
 http://github.com/Seldaek

Working at Nelmio
 http://nelm.io
 Symfony, app architecture & performance consulting

Semantic Versioning

semver.org

MAJOR . MINOR . PATCH

1 . 2 . 3

MAJOR . MINOR . PATCH

Breaks           Features           Fixes  

Dev
  -> 0.1.0

Fixes
  -> 0.1.1

Breaking changes
  -> 0.2.0

First stable
  -> 1.0.0

Fixes
  -> 1.0.1

Fixes
  -> 1.0.2

New features
  -> 1.1.0

Breaking changes
  -> 2.0.0

Version Constraints

Exact Match

1.0.0   1.2.3-beta2   dev-master

Range

1.0.*   2.*

Unbounded Range (BAD)

>=1.0

Operators

, = AND    | = OR

Next Significant Release

~1.2   =   >=1.2.0,<2.0.0

Next Significant Release

~1.2.3   =   >=1.2.3,<1.3.0

Libraries should use ~

.. and you should too!

~

Installing new packages

Require uses ~

composer require monolog/monolog

Require uses ~

"monolog/monolog": "~1.11"

Composer Stabilities

Stabilities

dev -> alpha -> beta -> RC -> stable

Tags

2.0.2 -> stable

2.0.0-beta2 -> beta

Branches

2.0 -> 2.0.x-dev (dev)

master -> dev-master (dev)

lala-feature -> dev-lala-feature (dev)

Resolution Conflicts

Overly Strict Requirements

// composer.json
{
    "require": {
        "cool/alice": "~1.3",
        "lazy/bob": "~1.2"
    }
}

// dependencies
{
    "name": "cool/alice",
    "require": {
        "monolog/monolog": "~1.6"
    }
}
{
    "name": "lazy/bob",
    "require": {
        "monolog/monolog": ">=1.3,<1.5"
    }
}
            

Overly Strict Requirements

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for lazy/bob ~1.2 -> satisfiable by lazy/bob[1.4.0].
    - Installation request for cool/alice ~1.3 -> satisfiable by cool/alice[1.3.0].
    - lazy/bob 1.4.0 requires monolog/monolog >=1.3,<1.5 -> satisfiable by monolog/monolog[1.3.0, 1.3.1, 1.4.0, 1.4.1].
    - cool/alice 1.3.0 requires monolog/monolog ~1.6 -> satisfiable by monolog/monolog[1.6.0, 1.7.0].
    - Can only install one of: monolog/monolog[1.6.0, 1.3.0].
    - Can only install one of: monolog/monolog[1.6.0, 1.3.1].
    - Conclusion: don't install monolog/monolog 1.4.1
    - Conclusion: don't install monolog/monolog 1.7.0
    - Conclusion: don't install monolog/monolog 1.4.0
    - Conclusion: don't install monolog/monolog 1.6.0
            

Stability Resolution

// composer.json
{
    "minimum-stability": "beta",
    "require": {
        "monolog/monolog": "1.*",
        "symfony/symfony": "~2.4",
        "bad/package": "dev-master"
    }
}

// dependencies
{
    "name": "bad/package",
    "require": {
        "monolog/monolog": "dev-master",
    }
}
            

Stability Resolution

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for bad/package dev-master -> satisfiable by bad/package[dev-master].
    - bad/package dev-master requires monolog/monolog dev-master -> no matching package found.
            

Forced to require monolog in dev version

Stability Resolution

// composer.json
{
    "minimum-stability": "beta",
    "require": {
        "monolog/monolog": "1.*@dev",
        "symfony/symfony": "~2.4",
        "bad/package": "dev-master"
    }
}

// dependencies
{
    "name": "bad/package",
    "require": {
        "monolog/monolog": "dev-master",
    }
}
            

Stability Resolution

// monolog
{
    "name": "monolog/monolog",
    "extra": {
        "branch-alias": {
            "dev-master": "1.7.x-dev"
        }
    }
}
            

Stability Resolution

- Installing monolog/monolog (dev-master 5ad421d)
  Cloning 5ad421d6a1d5d7066a45b617e5164d309c4e2852
            

Stability Resolution

Six months later... monolog 2.0!

Stability Resolution

// monolog
{
    "name": "monolog/monolog",
    "extra": {
        "branch-alias": {
            "dev-master": "2.0.x-dev"
        }
    }
}
            

Stability Resolution

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for monolog/monolog 1.*@dev -> satisfiable by monolog/monolog[1.7.0].
    - Installation request for bad/package dev-master -> satisfiable by bad/package[dev-master].
    - bad/package dev-master requires monolog/monolog dev-master -> satisfiable by monolog/monolog[dev-master].
    - Can only install one of: monolog/monolog[1.7.0, dev-master].
            

Forced to require monolog 2.*@dev or dev-master.

master might have broken bad/package and our project.

The Lock File

composer.lock

Who adds it to .gitignore?

Don't ignore it!

Fast installs with low memory usage

Don't ignore it!

Reproducible installs

composer.lock

Commit it

Use it with composer install

Custom composer commands

Add commands to scripts

{
    "require-dev": {
        "phpunit/phpunit": "~4.0"
    },
    "bin-dir": "vendor/bin",
    "scripts": {
        "test": "phpunit"
    }
}
            

Run commands

composer test
compoesr test -- --filter Foo
            

Using a forked project

Using a forked project

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/Seldaek/symfony"
        }
    ],
    "require": {
        "symfony/symfony": "dev-master"
    }
}
            

Additional repositories take priority over the default ones

Using a forked project

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/Seldaek/symfony"
        }
    ],
    "require": {
        "symfony/symfony": "dev-my-patch"
    }
}
            

Your branches are available as well

Use composer show -v symfony/symfony to see available versions

Using a forked project

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/Seldaek/symfony"
        }
    ],
    "require": {
        "symfony/symfony": "dev-my-patch as 2.5.0"
    }
}
            

Toran Proxy

Fast and reliable installs

Mirrors git repos and zip files

Private package hosting

Easy web interface configuration

Share the love

Profits not only fund Toran but also Composer and Packagist maintenance

Check it out

toranproxy.com

Releasing Packages

README.md

Short story about what problems the code solves

How to use and contribute

License


Read "On Open Sourcing Libraries" goo.gl/uNTt7K

Tag Releases

Often

Before breaking BC

It's easy: git tag 1.3.0

CHANGELOG.md

gitk 1.3.0..master

List relevant additions and fixes

List BC breaks prominently

Write an UPGRADE.md if needed


                    ### 2.0.0 (2037-01-19)

                      * Break: foo() and bar() have been swapped
                      * Added 64bit support
                      * Added more amazing things
                      * Fixed that annoying bug
                      * Fixed performance of baz()
                

Thank you.

Questions?

jordi@nelm.io

@seldaek

slides.seld.be


Feedback:

http://joind.in/11943