Jordi Boggiano
@seldaek


Composer Best Practices

Composer

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

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

Check phppackagechecklist.com

That's PHP Package Checklist dot com

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()
                

Version Constraints

Exact Match

1.0.0   1.2.3-beta2   dev-master

Wildcard Range

1.0.*   2.*

Hyphen Range

1.0 - 2.0   =   >=1.0.0 <2.1

Hyphen Range

1.0.0 - 2.1.0   =   >=1.0.0 <=2.1.0

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

Caret / Semver Operator

^1.2.3   =   >=1.2.3 <2.0.0

Caret / Semver Operator

^0.3   =   >=0.3.0 <0.4.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)

Allowing various stabilities

{
    "require": {
        "foo/bar": "^1.0@dev",
        "foo/baz": "^1.0@alpha",
        "foo/qux": "1.0.x-dev"
    },
    "minimum-stability": "beta"
}
                

Allowing various stabilities

composer create-project unstable/project --stability dev
composer create-project unstable/project path/ ^1.0@dev
composer create-project unstable/project -s 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.*"
    }
}
            

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.* -> satisfiable by monolog/monolog[1.3.0, 1.3.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.3.1
    - Conclusion: don't install monolog/monolog 1.7.0
    - Conclusion: don't install monolog/monolog 1.3.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.12.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.12.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.12.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!

Reproducible installs

Don't ignore it!

Fast installs with low memory usage

composer.lock

Commit it

Use it with composer install

But maybe don't deploy it..

Custom composer commands

Add commands to scripts

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

Run commands

composer test
composer 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"
    }
}
            

Community

packanalyst.com

semver.mwl.be

melody.sensiolabs.org

versioneye.com/php/monolog:monolog/references

packagist.graphstory.com

github.com/ziadoz/awesome-php

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

Thank you.

Questions?

@seldaek

slides.seld.be


Feedback:

joind.in/13735