Advertisement

Composer, putting dependencies on the score

Lead Backend Engineer at Usabilla
Sep. 2, 2012
Advertisement

More Related Content

Advertisement

More from Rafael Dohms(20)

Advertisement

Composer, putting dependencies on the score

  1. Rafael Dohms / @rdohms C!"p#$r Putting your dependencies on the score
  2. Rafael Dohms photo credit: Eli White @rdohms Evangelist, Speaker and Contributor. Developer at WEBclusive. Enabler at AmsterdamPHP.
  3. %$ E&$v'(!r P)(*+ a general introduction to Composer Ev$r,-', *!"p#)./ the basic stuff you need to know Up/r'-)./ (! ' M'$0(r! advanced features for more complex scenarios 1.-)./ ,!2r (2.$ discovering and sharing libraries
  4. %$ E&$v'(!r P)(*+
  5. per project system wide central repository spread out channels open acceptance strict standards
  6. Pr!b&$": I need my team and my deployments to use consistent versions of the dependencies of my project
  7. Pr!b&$": I need my team and my deployments to use consistent versions of the dependencies of my project S!&2()!.:
  8. Pr!b&$": I need my team and my deployments to use consistent versions of the dependencies of my project S!&2()!.: PEAR
  9. Pr!b&$": I need my team and my deployments to use consistent versions of the dependencies of my project S!&2()!.: PEAR SVN Externals
  10. Pr!b&$": I need my team and my deployments to use consistent versions of the dependencies of my project S!&2()!.: PEAR SVN Externals Git Submodules
  11. Pr!b&$": I need my team and my deployments to use consistent versions of the dependencies of my project S!&2()!.: PEAR SVN Externals Git Submodules vendor management script
  12. Pr!b&$": I need my team and my deployments to use consistent versions of the dependencies of my project S!&2()!.: PEAR SVN Externals Git Submodules vendor management script C!"p#$r!
  13. A per-project dependency manager that allows you to declare a consistent list of dependencies and versions for your application, as well as a consistent way of sharing your libraries and making them discoverable using packagist.org
  14. Ev$r,-', C!"p#)./
  15. I.0('&&)./ C!"p#$r Local (embed) $ curl -s http://getcomposer.org/installer | php Global $ curl -s http://getcomposer.org/installer | php -- --install-dir=bin
  16. I.0('&&)./ C!"p#$r Local (embed) $ curl -s http://getcomposer.org/installer | php Global $ curl -s http://getcomposer.org/installer | php -- --install-dir=bin 3p: $ ln -s /usr/bin/composer.phar /usr/bin/composer
  17. I.0('&&)./ C!"p#$r
  18. I.0('&&)./ C!"p#$r $ composer.phar --version Composer version 6573fd3
  19. I.0('&&)./ C!"p#$r php $ composer.phar --version Composer version 6573fd3
  20. K$$p )( 2p-'($-!
  21. K$$p )( 2p-'($-! $ composer.phar self-update Updating to version 65e95ed. Downloading: 100%
  22. C!"p#$r 101
  23. C!"p#$r 101 $ cd ~/dev/myproject
  24. C!"p#$r 101 $ cd ~/dev/myproject $ vim composer.json { "require": { "silex/silex": "1.0.*" }, "minimum-stability": "dev" }
  25. C!"p#$r 101 $ cd ~/dev/myproject $ vim composer.json note: project root { "require": { "silex/silex": "1.0.*" }, "minimum-stability": "dev" }
  26. C!"p#$r 101 $ cd ~/dev/myproject $ vim composer.json note: project root “require”: required packages and { versions "require": { "silex/silex": "1.0.*" adv. ex.: >=1.0.0,<1.2-dev }, "minimum-stability": "dev" }
  27. C!"p#$r 101 $ cd ~/dev/myproject $ vim composer.json note: project root “require”: required packages and { versions "require": { "silex/silex": "1.0.*" adv. ex.: >=1.0.0,<1.2-dev }, "minimum-stability": "dev" “minimum-stability”: if you only } want stable packages default: stable
  28. C!"p#$r 101 $ cd ~/dev/myproject $ vim composer.json note: project root “require”: required packages and { versions "require": { "silex/silex": "1.0.*" adv. ex.: >=1.0.0,<1.2-dev }, "minimum-stability": "dev" “minimum-stability”: if you only } want stable packages default: stable $ composer.phar install
  29. Installing dependencies - Installing pimple/pimple (dev-master) Cloning d2cfa2f02f50abef65c238747c753a5f6786f6be - Installing symfony/routing (dev-master) Cloning 6bca82c3ea0d42d750de4f49b22020dfd047dc0f [...] - Installing silex/silex (dev-master) Cloning 18e248a277adb061602d2bcabe96011db1c76ec0 symfony/routing suggests installing symfony/config (dev-master) symfony/routing suggests installing symfony/yaml (dev-master) symfony/routing suggests installing doctrine/common (>=2.2,<2.3) [...] silex/silex suggests installing symfony/browser-kit (2.1.*) silex/silex suggests installing symfony/css-selector (2.1.*) silex/silex suggests installing symfony/dom-crawler (2.1.*) Writing lock file Generating autoload files
  30. Installing dependencies - Installing pimple/pimple (dev-master) your Cloning d2cfa2f02f50abef65c238747c753a5f6786f6be dependency’s - Installing symfony/routing (dev-master) dependencies Cloning 6bca82c3ea0d42d750de4f49b22020dfd047dc0f [...] - Installing silex/silex (dev-master) Cloning 18e248a277adb061602d2bcabe96011db1c76ec0 symfony/routing suggests installing symfony/config (dev-master) symfony/routing suggests installing symfony/yaml (dev-master) symfony/routing suggests installing doctrine/common (>=2.2,<2.3) [...] silex/silex suggests installing symfony/browser-kit (2.1.*) silex/silex suggests installing symfony/css-selector (2.1.*) silex/silex suggests installing symfony/dom-crawler (2.1.*) Writing lock file Generating autoload files
  31. Installing dependencies - Installing pimple/pimple (dev-master) your Cloning d2cfa2f02f50abef65c238747c753a5f6786f6be dependency’s - Installing symfony/routing (dev-master) dependencies Cloning 6bca82c3ea0d42d750de4f49b22020dfd047dc0f [...] - Installing silex/silex (dev-master) your dependency Cloning 18e248a277adb061602d2bcabe96011db1c76ec0 symfony/routing suggests installing symfony/config (dev-master) symfony/routing suggests installing symfony/yaml (dev-master) symfony/routing suggests installing doctrine/common (>=2.2,<2.3) [...] silex/silex suggests installing symfony/browser-kit (2.1.*) silex/silex suggests installing symfony/css-selector (2.1.*) silex/silex suggests installing symfony/dom-crawler (2.1.*) Writing lock file Generating autoload files
  32. Installing dependencies - Installing pimple/pimple (dev-master) your Cloning d2cfa2f02f50abef65c238747c753a5f6786f6be dependency’s - Installing symfony/routing (dev-master) dependencies Cloning 6bca82c3ea0d42d750de4f49b22020dfd047dc0f [...] - Installing silex/silex (dev-master) your dependency Cloning 18e248a277adb061602d2bcabe96011db1c76ec0 symfony/routing suggests installing symfony/config (dev-master) symfony/routing suggests installing symfony/yaml (dev-master) symfony/routing suggests installing doctrine/common (>=2.2,<2.3) [...] silex/silex suggests installing symfony/browser-kit (2.1.*) silex/silex suggests installing symfony/css-selector (2.1.*) silex/silex suggests installing symfony/dom-crawler (2.1.*) Writing lock file Generating autoload files suggestions of other packages, for further features
  33. P)*42p (+$ ($"p!! Let Composer bootstrap you development
  34. B!!(0(r'pp)./ Pr!5$*(0 $ composer.phar create-project fabpot/silex-skeleton ~/dev/myproject
  35. B!!(0(r'pp)./ Pr!5$*(0 $ composer.phar create-project fabpot/silex-skeleton ~/dev/myproject Installing fabpot/silex-skeleton (dev-master cc19d406cf3cac253715db92d400992d4f3e1b52) - Installing fabpot/silex-skeleton (dev-master) Cloning master Created project in one-liner/ Installing dependencies - Installing pimple/pimple (dev-master) Cloning d2cfa2f02f50abef65c238747c753a5f6786f6be [...] symfony/routing suggests installing symfony/yaml (dev-master) [...] Writing lock file Generating autoload files
  36. B!!(0(r'pp)./ Pr!5$*(0 $ composer.phar create-project fabpot/silex-skeleton ~/dev/myproject Installing fabpot/silex-skeleton (dev-master cc19d406cf3cac253715db92d400992d4f3e1b52) - Installing fabpot/silex-skeleton (dev-master) Cloning master Created project in one-liner/ myproje Installing dependencies ct/ - Installing pimple/pimple (dev-master) compose r.json Cloning d2cfa2f02f50abef65c238747c753a5f6786f6be compose r.lock config/ [...] console / src/ templat symfony/routing suggests installing symfony/yaml (dev-master) es/ vendor/ [...] web/ Writing lock file Generating autoload files
  37. I w'.( (! *!.(r)b2($ ' pr!5$*( Composer can set that up for you.
  38. B!!(0(r'pp)./ C!.(r)b2()!.0 $ composer.phar create-project dms/dms --dev ~/dev/oss/dms
  39. B!!(0(r'pp)./ C!.(r)b2()!.0 gimme dev packages $ composer.phar create-project dms/dms --dev ~/dev/oss/dms
  40. B!!(0(r'pp)./ C!.(r)b2()!.0 gimme dev packages $ composer.phar create-project dms/dms --dev ~/dev/oss/dms     "require-dev": {         "symfony/symfony": ">=2.1-dev",         "doctrine/orm": "dev-master"     },
  41. B!!(0(r'pp)./ C!.(r)b2()!.0 gimme dev packages $ composer.phar create-project dms/dms --dev ~/dev/oss/dms     "require-dev": {         "symfony/symfony": ">=2.1-dev",         "doctrine/orm": "dev-master"     }, “require-dev”: only needed if you are going to contribute
  42. H!w -! I 6.-/&!'- (+$ 6&$0? PSR-0 and the modern autoloader
  43. Composer generates an autoload file for all your dependencies
  44. Composer generates an autoload file for all your dependencies vendor/autoload.php
  45. "autoload": {     "psr-0": { "MyNamespace": "<root>" }, "classmap": ["src/", "lib/", "Something.php"], "files": ["src/MyLibrary/functions.php"] },
  46. “autoload”: describes the autoloading needed for your library "autoload": {     "psr-0": { "MyNamespace": "<root>" }, "classmap": ["src/", "lib/", "Something.php"], "files": ["src/MyLibrary/functions.php"] },
  47. “autoload”: describes the autoloading needed for your library "autoload": {     "psr-0": { "MyNamespace": "<root>" “psr-0”: PSR-0 Compatible libraries }, "classmap": ["src/", "lib/", "Something.php"], "files": ["src/MyLibrary/functions.php"] },
  48. “autoload”: describes the autoloading needed for your library "autoload": {     "psr-0": { "MyNamespace": "<root>" “psr-0”: PSR-0 Compatible libraries }, "classmap": ["src/", "lib/", "Something.php"], PEAR packages and “classmap”: Old other libraries "files": ["src/MyLibrary/functions.php"] },
  49. “autoload”: describes the autoloading needed for your library "autoload": {     "psr-0": { "MyNamespace": "<root>" “psr-0”: PSR-0 Compatible libraries }, "classmap": ["src/", "lib/", "Something.php"], PEAR packages and “classmap”: Old other libraries "files": ["src/MyLibrary/functions.php"] “files”: for php functions or initializations },
  50. I.0('&&)./, 2p-'()./ '.- "!v)./ !. how does Composer guarantee consistency
  51. composer.json
  52. “composer.json”: metadata and list of your dependencies. composer.json
  53. “composer.json”: metadata and list of your dependencies. composer.json composer.lock
  54. “composer.json”: metadata and list of your dependencies. composer.json composer.lock “composer.lock”: existing dependencies and current commit hashes.
  55. composer.json composer.lock
  56. update composer.json composer.lock
  57. update install composer.json composer.lock
  58. update install reads composer.json composer.lock
  59. update install reads composer.json composer.lock gets latest
  60. update install reads composer.json writes composer.lock gets latest
  61. update install reads reads composer.json writes composer.lock gets latest
  62. update install reads reads composer.json compares writes composer.lock gets latest
  63. update install reads reads composer.json compares writes composer.lock gets latest gets locked version
  64. D$v$&!p)./ '. App ). ' ($'"? Commit you composer.lock file into the repository, and use composer install.
  65. D$v$&!p)./ '. App ). ' ($'"? Commit you composer.lock file into the repository, and use composer install. will ensure everyone is on the same “page”
  66. I’" -$v$&!p)./ ' &)br'r,, +$&p! here are some fields you should care about
  67. { "name": "vendor-namespace/package-name", "type": "symfony-bundle", "description": "A sample package for examples", "keywords": ["php", "package"], "homepage": "http://doh.ms", "license": "MIT", "support": { "email": "support@mylib.com", "issues": "http://issues.lib.com" } "target-dir": "/folder/to/install", }
  68. “name”: this should be unique, pick a good one! { "name": "vendor-namespace/package-name", "type": "symfony-bundle", "description": "A sample package for examples", "keywords": ["php", "package"], "homepage": "http://doh.ms", "license": "MIT", "support": { "email": "support@mylib.com", "issues": "http://issues.lib.com" } "target-dir": "/folder/to/install", }
  69. “name”: this should be unique, pick a good one! { "name": "vendor-namespace/package-name", “type”: will be used for more "type": "symfony-bundle", advanced “custom”installs "description": "A sample package for examples", "keywords": ["php", "package"], "homepage": "http://doh.ms", "license": "MIT", "support": { "email": "support@mylib.com", "issues": "http://issues.lib.com" } "target-dir": "/folder/to/install", }
  70. “name”: this should be unique, pick a good one! { "name": "vendor-namespace/package-name", “type”: will be used for more "type": "symfony-bundle", advanced “custom”installs "description": "A sample package for examples", "keywords": ["php", "package"], "homepage": "http://doh.ms", "license": "MIT", “license”: very important! "support": { "email": "support@mylib.com", "issues": "http://issues.lib.com" } "target-dir": "/folder/to/install", }
  71. “name”: this should be unique, pick a good one! { "name": "vendor-namespace/package-name", “type”: will be used for more "type": "symfony-bundle", advanced “custom”installs "description": "A sample package for examples", "keywords": ["php", "package"], "homepage": "http://doh.ms", "license": "MIT", “license”: very important! "support": { “support”: point people the right "email": "support@mylib.com", "issues": "http://issues.lib.com" way. } "target-dir": "/folder/to/install", }
  72. “name”: this should be unique, pick a good one! { "name": "vendor-namespace/package-name", “type”: will be used for more "type": "symfony-bundle", advanced “custom”installs "description": "A sample package for examples", "keywords": ["php", "package"], "homepage": "http://doh.ms", "license": "MIT", “license”: very important! "support": { “support”: point people the right "email": "support@mylib.com", "issues": "http://issues.lib.com" way. } "target-dir": "/folder/to/install", } “target-dir”: great for installing sub-dir splits repositories ex: Symfony Bundles: /Acme/Bundle/MyBundle
  73. M, *!-$ )0 PHP 5.4 !.&,! managing system dependencies
  74. { "require": { "php": ">=5.3.3", "ext-ldap": "*" } }
  75. { “php”: PHP version. "require": { "php": ">=5.3.3", "ext-ldap": "*" } }
  76. { “php”: PHP version. "require": { "php": ">=5.3.3", "ext-ldap": "*" } “ext-*”: Presence of selected } extension
  77. Up/r'-)./ (! ' M'$0(r!
  78. B2( I .$$- ' 0p$*)6* v$r0)!. version modifiers to the rescue!
  79. "acme/foo": "1.0.x-dev#3ebbe75"
  80. “#<ref>”: Get this specific commit "acme/foo": "1.0.x-dev#3ebbe75"
  81. “#<ref>”: Get this specific commit "acme/foo": "1.0.x-dev#3ebbe75" "acme/foo": "@dev" "acme/foo": "1.0.*@beta"
  82. “#<ref>”: Get this specific commit "acme/foo": "1.0.x-dev#3ebbe75" "acme/foo": "@dev" "acme/foo": "1.0.*@beta" “@<state>”: Get a version outside your default stability
  83. I .$$- (! 7$*2($ ' f$w 0*r)p(0 how to automate tasks with Composer
  84.     "scripts": {         "post-install-cmd": [             "SensioBundleDistributionBundleComposerScriptHandler::buildBootstrap",             "SensioBundleDistributionBundleComposerScriptHandler::clearCache",             "SensioBundleDistributionBundleComposerScriptHandler::installAssets",             "SensioBundleDistributionBundleComposerScriptHandler::installRequirementsFile"         ],         "post-update-cmd": [             "SensioBundleDistributionBundleComposerScriptHandler::buildBootstrap",             "SensioBundleDistributionBundleComposerScriptHandler::clearCache",             "SensioBundleDistributionBundleComposerScriptHandler::installAssets",             "SensioBundleDistributionBundleComposerScriptHandler::installRequirementsFile"         ]     },
  85. “scripts”: allows you to run scripts at given moments     "scripts": {         "post-install-cmd": [             "SensioBundleDistributionBundleComposerScriptHandler::buildBootstrap",             "SensioBundleDistributionBundleComposerScriptHandler::clearCache",             "SensioBundleDistributionBundleComposerScriptHandler::installAssets",             "SensioBundleDistributionBundleComposerScriptHandler::installRequirementsFile"         ],         "post-update-cmd": [             "SensioBundleDistributionBundleComposerScriptHandler::buildBootstrap",             "SensioBundleDistributionBundleComposerScriptHandler::clearCache",             "SensioBundleDistributionBundleComposerScriptHandler::installAssets",             "SensioBundleDistributionBundleComposerScriptHandler::installRequirementsFile"         ]     },
  86. C20(!" R$p#)(!r)$0 !r .! C!"p#$r, w+'( .!w? Injecting Composer into wild packages
  87. “hero/superpackage”: “dev-master”
  88. “hero/superpackage”: “dev-master”
  89. “hero/superpackage”: “dev-master”
  90. “hero/superpackage”: “dev-master”
  91. “hero/superpackage”: “dev-master”     "repositories": [ { "type": "vcs", "url": "https://github.com/rdohms/hero-superpackage" }        ]
  92. “hero/superpackage”: “dev-master” “repositories”: point to non-indexed, override existing or on- the-fly packages     "repositories": [ { "type": "vcs", "url": "https://github.com/rdohms/hero-superpackage" }        ]
  93. N!.-C!"p#$r P'*4'/$ { "repositories": [ { "type": "package", "package": { "name": "smarty/smarty", "version": "3.1.7", "dist": { "url": "http://www.smarty.net/files/Smarty-3.1.7.zip", "type": "zip" }, "source": { "url": "http://smarty-php.googlecode.com/svn/", "type": "svn", "reference": "tags/Smarty_3_1_7/distribution/" } } } ] }
  94. N!.-C!"p#$r P'*4'/$ { "repositories": [ “package”: on-the-fly package, injecting a { composer.json "type": "package", "package": { "name": "smarty/smarty", "version": "3.1.7", "dist": { "url": "http://www.smarty.net/files/Smarty-3.1.7.zip", "type": "zip" }, "source": { "url": "http://smarty-php.googlecode.com/svn/", "type": "svn", "reference": "tags/Smarty_3_1_7/distribution/" } } } ] }
  95. N!.-C!"p#$r P'*4'/$ { "repositories": [ “package”: on-the-fly package, injecting a { composer.json "type": "package", "package": { "name": "smarty/smarty", "version": "3.1.7", "dist": { "url": "http://www.smarty.net/files/Smarty-3.1.7.zip", "type": "zip" SVN / Git }, "source": { "url": "http://smarty-php.googlecode.com/svn/", "type": "svn", "reference": "tags/Smarty_3_1_7/distribution/" } } } ] }
  96. I .$$- (+)0 PEAR p'*4'/$... No Problem!
  97. { "repositories": [ { "type": "pear", "url": "http://pear2.php.net" } ], "require": { "pear-pear2.php.net/PEAR2_Text_Markdown": "*", "pear-pear2/PEAR2_HTTP_Request": "*" } }
  98. { “pear”: official PEAR and custom PEAR "repositories": [ channels { "type": "pear", "url": "http://pear2.php.net" } ], "require": { "pear-pear2.php.net/PEAR2_Text_Markdown": "*", "pear-pear2/PEAR2_HTTP_Request": "*" } }
  99. { “pear”: official PEAR and custom PEAR "repositories": [ channels { "type": "pear", "url": "http://pear2.php.net" } ], "require": { "pear-pear2.php.net/PEAR2_Text_Markdown": "*", "pear-pear2/PEAR2_HTTP_Request": "*" } } Remember the prefix!
  100. { “pear”: official PEAR and custom PEAR "repositories": [ channels { "type": "pear", "url": "http://pear2.php.net" } ], "require": { "pear-pear2.php.net/PEAR2_Text_Markdown": "*", "pear-pear2/PEAR2_HTTP_Request": "*" } } Remember the prefix! !! Warning: PEAR causes a overhead of requests
  101. alias replace provide
  102. alias { "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "require": { "monolog/monolog": "dev-bugfix as 1.0.x-dev" } } replace provide
  103. alias { "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "require": { "monolog/monolog": "dev-bugfix as 1.0.x-dev" } } replace provide “replace”: allows you to replace other packages, and be used them in their place.
  104. alias { "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "require": { "monolog/monolog": "dev-bugfix as 1.0.x-dev" } } replace provide “replace”: allows you to “provide”: allows you to say replace other packages, and a package provides a be used them in their place. expectation.
  105. 1.-)./ ,!2r (2.$
  106. I .$$- ' &)br'r, (+'( -!$0.. Let me get that for you
  107. http://packagist.org/
  108. usage info package info versions
  109. $ composer.phar search filter
  110. $ composer.phar search filter dms/dms-filter-bundle : DMS Filter Bundle, makes Annotation based ... lexik/form-filter-bundle : This bundle aim to provide classes to build... rollerworks/recordfilter-bundle : Record search-filtering bundle for Symfony brikou/zend_filter : Zend Framework Filter Library ext-filter : The filter PHP extension dms/dms-filter : DMS Library, includes various bundles and ... shtumi/useful-bundle : Symfony ShtumiUsefulBundle
  111. $ composer.phar show dms/dms-filter-bundle
  112. $ composer.phar show dms/dms-filter-bundle name : dms/dms-filter-bundle descrip. : DMS Filter Bundle, makes Annotation based entity filtering available in Symfony keywords : symfony, bundle, filter, dms versions : dev-master, v1.1.1, v1.1, 1.0.2, 1.0.1, 1.0.0 type : symfony-bundle license : MIT source : [git] https://github.com/rdohms/DMSFilterBundle v1.1.1 dist : [zip] https://github.com/rdohms/DMSFilterBundle/zipball/ v1.1.1 v1.1.1 names : dms/dms-filter-bundle autoload psr-0 DMSBundleFilterBundle => . requires php >=5.3.2 dms/dms-filter >=1.0.2
  113. B2( ", r$p#)(!r, )0 pr)v'($! Get your own package repository
  114. S'()0!
  115. R!&&!2( ,!2r !w. S'()0 $ composer.phar create-project composer/satis
  116. R!&&!2( ,!2r !w. S'()0 $ composer.phar create-project composer/satis $ vi packages.json { "name": "My Repository", "homepage": "http://packages.example.org", "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-all": true }
  117. R!&&!2( ,!2r !w. S'()0 $ composer.phar create-project composer/satis $ vi packages.json { "name": "My Repository", "homepage": "http://packages.example.org", "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-all": true } $ php bin/satis build config.json web/
  118. U0)./ ,!2r !w. S'()0 { "repositories": [ { "type": "composer", "url": "http://packages.yourdomain.net" } ], “require”: { “myvendor/mypackage”: “dev-master” } }
  119. U0)./ ,!2r !w. S'()0 { "repositories": [ “composer”: use this just like it was Packagist { "type": "composer", "url": "http://packages.yourdomain.net" } ], “require”: { “myvendor/mypackage”: “dev-master” } }
  120. W+$r$ 0+!2&- I /$( +$&p? http://getcomposer.org #composer on irc.freenode.org
  121. %$ E&$v'(!r P)(*+ Dependency Manager, consistent versions, per-project Ev$r,-', *!"p#)./ install, update, lock and autoload Up/r'-)./ (! ' M'$0(r! post-install, overriding, PEAR integration, developer environment 1.-)./ ,!2r (2.$ Satis and Packagist
  122. %'.4 ,!2! https://joind.in/7051 @rdohms http://doh.ms http://slides.doh.ms
Advertisement