Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Managing Dependencies with Composer (php[tek] 2015)

Managing Dependencies with Composer (php[tek] 2015)

Traditionally, managing third-party code in PHP projects has not been a trivial task. Fortunately, the PHP community now has Composer, a top-notch dependency manager. Learn what Composer is and how you can put it to work for fun and profit. You will see how to set up a new project, find packages, as well as how to create and distribute your own packages.

Beau Simensen

May 19, 2015
Tweet

More Decks by Beau Simensen

Other Decks in Programming

Transcript

  1. Managing Dependencies
    with Composer
    php[tek]
    May 19th, 2015
    @beausimensen
    beau.io joind.in/13769

    View Slide

  2. View Slide

  3. Tutorial

    View Slide

  4. Wi-Fi & PHP>=5.3.2
    required if you want to play

    View Slide

  5. $ composer show [pkg]
    shows information about a package

    View Slide

  6. $ composer show silex/silex
    shows information about Silex

    View Slide

  7. Dependency
    Management

    View Slide

  8. composer.json

    View Slide

  9. {
    “name”: “acme/my-project”,
    “description”: “Acme’s My Project”,
    “license”: “MIT”,
    “require”: {
    “silex/silex”: “1.1.*”
    },
    “autoload”: {
    “psr-4”: {
    “Acme\\MyProject\\”: “src”
    }
    }
    }

    View Slide

  10. {
    “name”: “acme/my-project”,
    “description”: “Acme’s My Project”,
    “license”: “MIT”,
    “require”: {
    “silex/silex”: “1.1.*”
    },
    “autoload”: {
    “psr-4”: {
    “Acme\\MyProject\\”: “src”
    }
    }
    }

    View Slide

  11. vendor-name/project-name
    A package's name cannot change and must be all lowercase

    View Slide

  12. http://www.spdx.org/licenses/
    Publishing to Packagist requires you choose a license!

    View Slide

  13. {
    “name”: “acme/my-project”,
    “description”: “Acme’s My Project”,
    “license”: “MIT”,
    “require”: {
    “silex/silex”: “1.1.*”
    },
    “autoload”: {
    “psr-4”: {
    “Acme\\MyProject\\”: “src”
    }
    }
    }

    View Slide

  14. {
    “name”: “acme/my-project”,
    “description”: “Acme’s My Project”,
    “license”: “MIT”,
    “require”: {
    “silex/silex”: “1.1.*”
    },
    “autoload”: {
    “psr-4”: {
    “Acme\\MyProject\\”: “src”
    }
    }
    }

    View Slide

  15. $ composer install
    Loading composer repositories with package information
    Installing dependencies (including require-dev)
    - Installing psr/log (1.0.0)
    - Installing symfony/routing (v2.3.7)
    - Installing symfony/debug (v2.3.7)
    - Installing symfony/http-foundation (v2.3.7)
    - Installing symfony/event-dispatcher (v2.3.7)
    - Installing symfony/http-kernel (v2.3.7)
    - Installing pimple/pimple (v1.1.0)
    - Installing silex/silex (v1.1.2)
    Writing lock file
    Generating autoload files
    $

    View Slide

  16. The packages are installed into a
    directory named vendor

    View Slide

  17. vendor =

    View Slide

  18. require “vendor/autoload.php”;

    View Slide

  19. Basic Usage

    View Slide

  20. Install Composer
    getcomposer.org/download

    View Slide

  21. $ curl -sS https://getcomposer.org/installer | php
    $ php composer.phar --version
    WARNING
    Security people think this is bad (but it is all the rage)

    View Slide

  22. $ chmod 755 composer.phar
    $ mv composer.phar ~/bin/composer
    $ composer --version

    View Slide

  23. composer.json and composer.lock

    View Slide

  24. composer.json describes a
    package and its dependencies

    View Slide

  25. {
    “name”: “acme/my-project”,
    “description”: “Acme’s My Project”,
    “license”: “MIT”,
    “require”: {
    “silex/silex”: “1.1.*”
    },
    “autoload”: {
    “psr-4”: {
    “Acme\\MyProject\\”: “src”
    }
    }
    }

    View Slide

  26. composer.lock describes
    exactly what should be installed

    View Slide

  27. $ composer install
    Loading composer repositories with package information
    Installing dependencies (including require-dev)
    - Installing psr/log (1.0.0)
    - Installing symfony/routing (v2.3.7)
    - Installing symfony/debug (v2.3.7)
    - Installing symfony/http-foundation (v2.3.7)
    - Installing symfony/event-dispatcher (v2.3.7)
    - Installing symfony/http-kernel (v2.3.7)
    - Installing pimple/pimple (v1.1.0)
    - Installing silex/silex (v1.1.2)
    Writing lock file
    Generating autoload files
    $

    View Slide

  28. Check your composer.lock into
    your repository

    View Slide

  29. Common Commands

    View Slide

  30. $ composer install
    If composer.lock exists, install exactly what is in the lock file.
    !
    Otherwise, read composer.json to find out what should be installed,
    install the dependencies, and write out composer.lock.

    View Slide

  31. View Slide

  32. View Slide

  33. View Slide

  34. View Slide

  35. $ composer update
    Installs dependencies from composer.json
    and creates or updates composer.lock.

    View Slide

  36. View Slide

  37. View Slide

  38. View Slide

  39. View Slide

  40. $ composer require [pkg]
    Add a package to composer.json.
    !
    The [pkg] is the name with a version constraint.
    !
    !
    foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"

    View Slide

  41. $ composer require [pkg]
    Recommend way to add Composer packages to your project!
    !
    composer require foo/bar

    View Slide

  42. View Slide

  43. $ composer require --dev [pkg]
    Add a package as a dev requirement
    !
    composer require --dev foo/bar

    View Slide

  44. View Slide

  45. View Slide

  46. View Slide

  47. View Slide

  48. $ composer validate
    Check composer.json for common errors

    View Slide

  49. View Slide

  50. $ composer diag
    Check environment and composer.json for common errors

    View Slide

  51. View Slide

  52. View Slide

  53. $ composer show [pkg]
    shows information about a package

    View Slide

  54. View Slide

  55. $ composer show --self
    shows information about THIS package

    View Slide

  56. View Slide

  57. $ composer clearcache
    Because sometimes things get stale.

    View Slide

  58. Vendor Tour

    View Slide

  59. vendor =

    View Slide

  60. View Slide

  61. View Slide

  62. {
    “name”: “acme/my-project”,
    “description”: “Acme’s My Project”,
    “license”: “MIT”,
    “require”: {
    “silex/silex”: “1.1.*”
    },
    “autoload”: {
    “psr-4”: {
    “Acme\\MyProject\\”: “src”
    }
    }
    }

    View Slide

  63. Autoloading

    View Slide

  64. # Acme\User is not defined
    !
    $user = new Acme\User();
    !
    # Acme\User is defined

    View Slide

  65. Magic!
    since 5

    View Slide

  66. function ($class) {
    if ($class === "Acme\\Account\\User") {
    // do something to cause this class
    // to become defined
    require __DIR__."/src/user.inc";
    }
    }

    View Slide

  67. Composer is a configurable
    autoloader

    View Slide

  68. Each Composer package gets
    to configure its own rules

    View Slide

  69. psr-0

    View Slide

  70. PHP-FIG
    PHP Framework Interoperability Group
    php-fig.com

    View Slide

  71. Namespaces are directories

    View Slide

  72. Classes are files with .php suffix

    View Slide

  73. Acme\Account\User

    View Slide

  74. Acme/Account/User.php

    View Slide

  75. PSR-0 also supports legacy
    PEAR style naming conventions

    View Slide

  76. Acme\Account\User
    !
    Acme_Account_User

    View Slide

  77. Acme/Account/User.php
    !
    Acme/Account/User.php

    View Slide

  78. {
    "autoload": {
    "psr-0": {
    "Acme\\Account\\": "src"
    }
    }
    }
    !
    new Acme\Account\User();
    !
    # src/Acme/Account/User.php

    View Slide

  79. {
    "autoload": {
    "psr-0": {
    "Acme_Account_": "src"
    }
    }
    }
    !
    new Acme_Account_User();
    !
    # src/Acme/Account/User.php

    View Slide

  80. psr-4

    View Slide

  81. PHP-FIG
    PHP Framework Interoperability Group
    php-fig.com

    View Slide

  82. Composer currently recommends
    new projects use PSR-4

    View Slide

  83. Very similar to PSR-0

    View Slide

  84. Only supports namespaces
    (this means no PEAR style naming)

    View Slide

  85. Requires a namespace prefix
    and base directory for mapping

    View Slide

  86. Acme\Account\User (class)
    !
    Acme\Account (namespace prefix)
    !
    src (base directory)
    !
    src/User.php (resulting file path)

    View Slide

  87. {
    "autoload": {
    "psr-4": {
    "Acme\\Account\\": "src"
    }
    }
    }
    !
    new Acme\Account\User();
    !
    # src/User.php

    View Slide

  88. Migrating from PSR-0 to PSR-4

    View Slide

  89. {
    "autoload": {
    "psr-0": {
    "Acme\\Account\\": "src"
    }
    }
    }
    !
    new Acme\Account\User();
    !
    # src/Acme/Account/User.php

    View Slide

  90. {
    "autoload": {
    "psr-4": {
    "Acme\\Account\\": "src/Acme/Account"
    }
    }
    }
    !
    new Acme\Account\User();
    !
    # src/Acme/Account/User.php

    View Slide

  91. files

    View Slide

  92. Explicitly include specific files

    View Slide

  93. {
    “autoload”: {
    “files”: [
    “src/foo.class.php”,
    “src/bar.class.php”
    ]
    }
    }

    View Slide

  94. {
    “autoload”: {
    “files”: [“src/functions.php”]
    }
    }

    View Slide

  95. {
    “autoload”: {
    “files”: [“src/autoload.php”]
    }
    }

    View Slide

  96. The files autoloader is really
    an alwaysloader

    View Slide

  97. classmap

    View Slide

  98. A key => value map of class
    names to files on disk

    View Slide

  99. {
    “autoload”: {
    “classmap”: [
    “src/includes/”,
    “resources/config.php”
    ]
    }
    }

    View Slide

  100. It will look inside .php and .inc
    files to find classes

    View Slide

  101. The classmap is generated anytime
    Composer dumps its autoloader

    View Slide

  102. Extremely fast and powerful but
    not very developer friendly

    View Slide

  103. {
    “name”: “acme/my-project”,
    “description”: “Acme’s My Project”,
    “license”: “MIT”,
    “require”: {
    “silex/silex”: “1.1.*”
    },
    “autoload”: {
    “psr-4”: {
    “Acme\\MyProject\\”: “src”
    }
    }
    }

    View Slide

  104. {
    “name”: “acme/my-project”,
    “description”: “Acme’s My Project”,
    “license”: “MIT”,
    “require”: {
    “silex/silex”: “1.1.*”
    },
    “autoload”: {
    “psr-4”: {
    “Acme\\MyProject\\”: “src”
    }
    }
    }

    View Slide

  105. Semantic Versioning

    View Slide

  106. semver.org

    View Slide

  107. MAJOR.MINOR.PATCH
    Which number do you increment and why?

    View Slide

  108. MAJOR.MINOR.PATCH
    When you break backwards compatibility

    View Slide

  109. MAJOR.MINOR.PATCH
    When you add backwards compatible features

    View Slide

  110. MAJOR.MINOR.PATCH
    When you make backwards compatible bug fixes

    View Slide

  111. Pre-Release Identifiers

    View Slide

  112. 1.0.0-alpha
    1.0.0-beta.2
    1.0.0-RC3

    View Slide

  113. Stability
    Pre-Release Identifiers

    View Slide

  114. Version Constraints

    View Slide

  115. Exact Version
    1.0.2

    View Slide

  116. Ranges
    >=1.0,<2.0

    View Slide

  117. Wildcards
    1.0.*

    View Slide

  118. Next Significant Release
    Tilde and Caret Operators

    View Slide

  119. Next Significant Release
    ~1.2
    Minimum allowed version and only
    the last number listed can increase.

    View Slide

  120. Next Significant Release
    ~1.2
    >=1.2,<2

    View Slide

  121. Next Significant Release
    ~1.2.3
    >=1.2.3,<1.3

    View Slide

  122. Next Significant Release
    ^1.2
    Minimum allowed version and up to
    next major release.

    View Slide

  123. Next Significant Release
    ^1.2
    >=1.2,<2

    View Slide

  124. Next Significant Release
    ^1.2.3
    >=1.2.3,<2

    View Slide

  125. Next Significant Release
    ^0.2
    Safer handling for pre-1.0 versions.

    View Slide

  126. Next Significant Release
    ^0.2
    >=0.2,<0.3

    View Slide

  127. Next Significant Release
    ^0.2.3
    >=0.2.3,<0.3

    View Slide

  128. Semantic Versioning lets
    you know what you are
    getting into

    View Slide

  129. Safe
    1.3.*
    Only get bug fixes

    View Slide

  130. Reasonably Safe
    1.*
    Get bug fixes and new features

    View Slide

  131. Nope.
    *
    Composer allows this, but don't.
    Just don't.

    View Slide

  132. Version Constraint Considerations

    View Slide

  133. –Semantic Versioning
    “If the dependency specifications are too tight, you are in danger
    of version lock (the inability to upgrade a package without having
    to release new versions of every dependent package).”

    View Slide

  134. Libraries should generally have
    more permissive constraints

    View Slide

  135. –Semantic Versioning
    “If dependencies are specified too loosely, you will inevitably
    be bitten by version promiscuity (assuming compatibility with
    more future versions than is reasonable).”

    View Slide

  136. End projects may want to have
    more restrictive constraints

    View Slide

  137. Deep Dependency Resolution

    View Slide

  138. {
    “name”: “silex/silex”,
    “require”: {
    “pimple/pimple”: “1.*”
    }
    }
    1.1.0
    1.1.0
    1.1.1
    1.0.2
    1.0.1
    1.0.0
    2.0.0
    Silex
    Pimple
    0.0.1

    View Slide

  139. {
    “name”: “silex/silex”,
    “require”: {
    “pimple/pimple”: “1.*”
    }
    }
    {
    “name”: “dflydev/doctrine-orm-service-provider”,
    “require”: {
    “pimple/pimple”: “~1.1”,
    “doctrine/orm”: “~2.3”
    }
    }
    1.1.0
    1.1.0
    1.1.1
    1.0.2
    1.0.1
    1.0.0
    2.0.0
    Silex
    Pimple
    0.0.1
    2.3.2
    2.4.0
    2.3.1
    2.3.0
    2.2.1
    2.5.0
    ORM
    2.2.0
    1.0.0
    dflydev

    View Slide

  140. {
    “name”: “acme/myapp”,
    “require”: {
    “dflydev/doctrine-orm-service-provider”: “1.0.*”,
    “silex/silex”: “1.1.*”,
    !
    “pimple/pimple”: “~1.1.1”,
    “doctrine/orm”: “2.4.*”
    }
    }
    {
    “name”: “silex/silex”,
    “require”: {
    “pimple/pimple”: “1.*”
    }
    }
    {
    “name”: “dflydev/doctrine-orm-service-provider”,
    “require”: {
    “pimple/pimple”: “~1.1”,
    “doctrine/orm”: “~2.3”
    }
    }
    1.1.0
    1.1.0
    1.1.1
    1.0.2
    1.0.1
    1.0.0
    2.0.0
    Silex
    Pimple
    0.0.1
    2.3.2
    2.4.0
    2.3.1
    2.3.0
    2.2.1
    2.5.0
    ORM
    2.2.0
    1.0.0
    dflydev
    1.0.0
    myapp

    View Slide

  141. Conflicts

    View Slide

  142. {
    "require": {
    "silex/silex": "1.1.*",
    "pimple/pimple": "2.0.*@dev"
    }
    }

    View Slide

  143. $ composer install
    Loading composer repositories with package information
    Installing dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.
    !
    Problem 1
    - silex/silex v1.1.0 requires pimple/pimple 1.*
    -> satisfiable by pimple/pimple[1.0.0, 1.1.x-dev, v1.0.1, v1.0.2, v1.1.0].
    - silex/silex v1.1.1 requires pimple/pimple 1.*
    -> satisfiable by pimple/pimple[1.0.0, 1.1.x-dev, v1.0.1, v1.0.2, v1.1.0].
    - silex/silex v1.1.2 requires pimple/pimple ~1.0
    -> satisfiable by pimple/pimple[1.0.0, 1.1.x-dev, v1.0.1, v1.0.2, v1.1.0].
    - Can only install one of: pimple/pimple[2.0.x-dev, 1.0.0].
    - Can only install one of: pimple/pimple[2.0.x-dev, 1.1.x-dev].
    - Can only install one of: pimple/pimple[v1.0.1, 2.0.x-dev].
    - Can only install one of: pimple/pimple[v1.0.2, 2.0.x-dev].
    - Can only install one of: pimple/pimple[v1.1.0, 2.0.x-dev].
    - Installation request for pimple/pimple 2.0.*@dev
    -> satisfiable by pimple/pimple[2.0.x-dev].
    - Installation request for silex/silex 1.1.*
    -> satisfiable by silex/silex[v1.1.0, v1.1.1, v1.1.2].
    !
    Potential causes:
    - A typo in the package name
    - The package is not available in a stable-enough version according to your
    minimum-stability setting.

    View Slide

  144. Versions from Tags

    View Slide

  145. 2.0.1
    2.0.1
    (2.0.*)

    View Slide

  146. v2.0.1
    2.0.1
    (2.0.*)

    View Slide

  147. 2.0.1-RC1
    2.0.1-RC1
    (2.0.*@RC)

    View Slide

  148. 3.4-cuddly-cat
    3.4-cuddly-cat
    (3.4-cuddly-cat)

    View Slide

  149. 2.0.1g
    2.0.1g
    (2.0.1g)

    View Slide

  150. Versions from Branches

    View Slide

  151. Branches are considered
    @dev stability

    View Slide

  152. Numbered branches are easy

    View Slide

  153. 2.0
    2.0.x-dev
    (2.0.*@dev)

    View Slide

  154. Named branches default to their
    name with a dev- prefix

    View Slide

  155. master
    dev-master
    (dev-master)

    View Slide

  156. 2.0-experimental
    dev-2.0-experimental
    (2.0.*@dev won't work!)

    View Slide

  157. Named branches can be aliased
    to be semver friendly

    View Slide

  158. {
    “extra”: {
    “branch-alias”: {
    “dev-master”: “2.0.x-dev”
    }
    }
    }

    View Slide

  159. master
    dev-master / 2.0.x-dev
    (dev-master or 2.0.*@dev)

    View Slide

  160. Create a branch alias as soon as
    you start a new Composer
    package

    View Slide

  161. (future you and your users will thank you)

    View Slide

  162. Requiring non-stable versions

    View Slide

  163. {
    “require”: {
    “symfony/yaml”: “3.5-cat”,
    “silex/silex”: “1.1@dev”,
    “pimple/pimple”: “dev-master”,
    “sculpin/core”: “2.0.*@beta”
    }
    }

    View Slide

  164. {
    “require”: {
    “symfony/yaml”: “3.5-cat”,
    “silex/silex”: “1.1@dev”,
    “pimple/pimple”: “dev-master”,
    “sculpin/core”: “2.0.*@beta”
    }
    }

    View Slide

  165. requiring dev-master
    considered harmful

    View Slide

  166. Pretend dev-master doesn't exist

    View Slide

  167. Send pull requests when you find
    a package that offers dev-master
    without a branch alias

    View Slide

  168. {
    “name”: “acme/myapp”
    }

    View Slide

  169. {
    “name”: “acme/myapp”,
    “require”: {
    “naughty/id-generator”: “1.0.*”
    }
    }
    !
    !
    {
    “name”: “naughty/id-generator”,
    “require”: {
    “ircmaxell/random-lib”: “dev-master”
    }
    }

    View Slide

  170. {
    “name”: “acme/myapp”,
    “require”: {
    “naughty/id-generator”: “1.0.*”,
    !
    “ircmaxell/random-lib”: “@dev”
    }
    }
    !
    !
    {
    “name”: “naughty/id-generator”,
    “require”: {
    “ircmaxell/random-lib”: “dev-master”
    }
    }

    View Slide

  171. {
    “name”: “acme/myapp”,
    “require”: {
    “naughty/id-generator”: “1.0.*”,
    !
    “ircmaxell/random-lib”: “dev-master”
    }
    }
    !
    !
    {
    “name”: “naughty/id-generator”,
    “require”: {
    “ircmaxell/random-lib”: “dev-master”
    }
    }

    View Slide

  172. {
    “name”: “acme/myapp”,
    “require”: {
    “naughty/id-generator”: “1.0.*”,
    "dflydev/hawk": "1.0.*",
    !
    "ircmaxell/random-lib": "dev-master"
    }
    }
    !
    !
    {
    “name”: “naughty/id-generator”,
    “require”: {
    “ircmaxell/random-lib”: “dev-master”
    }
    }
    !
    !
    {
    “name”: “dflydev/hawk”,
    “require”: {
    “ircmaxell/random-lib”: “~1.0@dev”
    }
    }

    View Slide

  173. {
    “name”: “acme/myapp”,
    “require”: {
    “naughty/id-generator”: "1.0.*”,
    "dflydev/hawk": "1.0.*",
    !
    "ircmaxell/random-lib": "dev-master"
    }
    }
    !
    !
    {
    “name”: “naughty/id-generator”,
    “require”: {
    “ircmaxell/random-lib”: “dev-master”
    }
    }
    !
    !
    {
    “name”: “dflydev/hawk”,
    “require”: {
    “ircmaxell/random-lib”: “~1.0@dev”
    }
    }
    1.0.x-dev != dev-master

    View Slide

  174. {
    “name”: “acme/myapp”,
    “require”: {
    “naughty/id-generator”: “1.0.*”,
    "dflydev/hawk": "1.0.*",
    !
    "ircmaxell/random-lib": "@dev"
    }
    }
    !
    !
    {
    “name”: “naughty/id-generator”,
    “require”: {
    “ircmaxell/random-lib”: “~1.0@dev”
    }
    }
    !
    !
    {
    “name”: “dflydev/hawk”,
    “require”: {
    “ircmaxell/random-lib”: “~1.0@dev”
    }
    }
    Time to send a
    pull request!

    View Slide

  175. dev-master is viral

    View Slide

  176. Once people start using dev-master
    for your package it can be hard to
    break them of that habit

    View Slide

  177. Send pull requests when you find a
    package that requires dev-master
    when a branch alias exists

    View Slide

  178. –Michael Dowling
    “I'm working on a new version of Guzzle. If you're using
    composer: stop using dev-master. Use a tagged
    release. Especially in production.”
    https://twitter.com/mtdowling/status/440901351657054208

    View Slide

  179. Stability

    View Slide

  180. Root package

    View Slide

  181. The root package is the package
    defined in the working
    composer.json

    View Slide

  182. A package is the root package
    while it is being developed

    View Slide

  183. The root package gets to control
    all aspects of stability

    View Slide

  184. Minimum stability

    View Slide

  185. Controlled by the root package

    View Slide

  186. Defaults to stable

    View Slide

  187. {
    “minimum-stability”: “alpha”
    }

    View Slide

  188. Applied to all packages for
    which the root package doesn't
    specify a stability

    View Slide

  189. Package-by-package stability

    View Slide

  190. Stability can be controlled on a
    package-by-package basis

    View Slide

  191. {
    “require”: {
    “silex/silex”: “~1.1@dev”,
    “symfony/http-foundation”: “@beta”
    },
    “minimum-stability”: “alpha”
    }

    View Slide

  192. Stability solver errors are fun

    View Slide

  193. {
    "require": {
    "sculpin/sculpin": "2.0.*"
    }
    }

    View Slide

  194. $ composer install
    Loading composer repositories with package information
    Installing dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of
    packages.
    !
    Problem 1
    - The requested package sculpin/sculpin 2.0.* could not be found.
    !
    Potential causes:
    - A typo in the package name
    - The package is not available in a stable-enough version according to
    your minimum-stability setting

    View Slide

  195. $ composer install
    Loading composer repositories with package information
    Installing dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of
    packages.
    !
    Problem 1
    - The requested package sculpin/sculpin 2.0.* could not be found.
    !
    Potential causes:
    - A typo in the package name
    - The package is not available in a stable-enough version according to
    your minimum-stability setting

    View Slide

  196. {
    "require": {
    "sculpin/sculpin": "2.0.*@dev"
    }
    }

    View Slide

  197. {
    "require": {
    "sculpin/sculpin": "2.0.*"
    },
    "minimum-stability": "dev"
    }

    View Slide

  198. Root package stability implications

    View Slide

  199. Even if your package requires a
    dependency @dev, users of your
    package won't get it unless they
    explicitly ask for it.

    View Slide

  200. {
    “name”: “silex/silex”,
    “require”: {
    “pimple/pimple”: “1.*@dev”
    }
    }
    Root Package

    View Slide

  201. {
    “name”: “silex/silex”,
    “require”: {
    “pimple/pimple”: “1.*@dev”
    }
    }
    {
    “name”: “dflydev/doctrine-orm-service-provider”,
    “require”: {
    “pimple/pimple”: “1.*@beta”,
    “silex/silex”: “1.1.*”,
    “doctrine/orm”: “~2.3”
    }
    }
    Root Package

    View Slide

  202. {
    “require”: {
    “dflydev/doctrine-orm-service-provider”: “1.0.*”,
    !
    “pimple/pimple”: “1.*@alpha”
    }
    }
    {
    “name”: “silex/silex”,
    “require”: {
    “pimple/pimple”: “1.*@dev”
    }
    }
    {
    “name”: “dflydev/doctrine-orm-service-provider”,
    “require”: {
    “pimple/pimple”: “1.*@beta”,
    “silex/silex”: “1.1.*”,
    “doctrine/orm”: “~2.3”
    }
    }
    Root Package

    View Slide

  203. Dev Dependencies

    View Slide

  204. dev dependencies can only be
    installed for the root package

    View Slide

  205. Publishing and
    Discovery

    View Slide

  206. packagist.org

    View Slide

  207. Over 59,200 packages

    View Slide

  208. Publishing is as easy as pasting
    your repository's GitHub URL

    View Slide

  209. View Slide

  210. Check Packagist before you
    start a new library from scratch

    View Slide

  211. Self Hosted Composer
    Repositories

    View Slide

  212. Install Packagist Locally

    View Slide

  213. Satis

    View Slide

  214. Toran Proxy
    https://toranproxy.com/

    View Slide

  215. [this page intentionally left blank]

    View Slide

  216. Choose an autoloading strategy

    View Slide

  217. Choose PSR-4 for new projects

    View Slide

  218. Semantic Versioning lets you
    know what you're getting into

    View Slide

  219. Libraries should generally have
    more permissive constraints

    View Slide

  220. End projects may want to have
    more restrictive constraints

    View Slide

  221. Create branch aliases

    View Slide

  222. dev-master considered harmful

    View Slide

  223. Use Packagist

    View Slide

  224. #composer
    look for simensen and say "hi"
    freenode IRC

    View Slide

  225. Questions?
    @beausimensen • beau.io
    @thatpodcast • thatpodcast.io
    beau.io/talks
    joind.in

    View Slide

  226. Beau Simensen
    @beausimensen
    +BeauSimensen
    beau.io

    View Slide

  227. Dragonfly Development
    @dflydev
    dflydev.com

    View Slide