From my experiences in #zftalk Zend Framework support channel on Freenode, it seems that lots of people still don’t understand the fundamental rules of using Composer in production. So I thought I’d run through some of the basic ideas behind using composer in development and production.
How you define the packages you use is actually fairly important. Define the packages you need to run the code in production under the “required” key, while things that should only be needed for development should be defined under the “required-dev” key. You don’t want to be pulling down packages that you use only for development (like PHPUnit, Roave Developer Tools, etc) onto your production environment, even if you are disabling them in the code.
On your development machine you will likely want to be working with the newest version of the dependant packages, and so you should use composer update to pull these down. Update will check the installed version that is logged to composer.lock, against the version that is available at the source (typically packagist). If there is a newer version available that complies with the version defined in your composer.json, then that will be downloaded and composer.lock will be updated with that current version.
Typically, on development you would want to run something like:
composer update --dev
This tells composer to update all packages, and install the packages that are defined in the require-dev key.
You don’t want to be installing new versions of packages on production. That seems like an obvious statement, but if you use composer update on production, that’s exactly what you’ll be doing. I’m presuming you have unit tests, integration tests, acceptance tests and all that jazz that you run in your development/staging environment. You’ll have run those tests against the versions of the packages in your composer.lock file, by using composer update as part of your deployment process you’ll effectively be negating all the good work you’ve done in testing the code in the first place.
You should definitely be keeping the composer.lock file in your version control, and as part of your build and deployment process you will want to be only pulling down the tested versions of the packages that you have stored in the composer.lock file. To do that we will use Composer’s install command.
The help for composer install tells us that it “Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.” which is exactly what we need. But we also need a couple of extra switches for safetly. Typically, in production we use:
composer install --no-dev --prefer-dist --no-interaction
This tells composer to install from the composer.lock file, to not install anything defined in require-dev, to always prefer the package version of the code in case of discrepancy, and not to ask any pesky questions of the user.
Hopefully that clears up why you shouldn’t use composer update in production.
— EDIT —
Due to overwhelming public demand, I would like to mention here that your production install command should also contain the switch –optimize-autoloader in order that you can squeeze some extra juice out of the already slow process of autoloading. I still think it’s out of scope of this post, but it’s too good a tip not to include. Thanks to Jurians, Mwop and Daniels for the nudge.