Composer is the defacto standard for package management in PHP. It’s simple, effective, and has become ubiquitous in the community.
Important Note: Composer major upgrade fix
Everybody knows that when using Composer you just create a
composer.json file with a list of dependencies and your desired versions, then run
composer install and you’re done.
You then commit the
composer.json to your project and everyone else on your team can run
composer install to install your project dependencies.
We also know that if you want to update your dependencies, you simply run
composer update. This will update the currently installed dependencies to their latest versions (as meets your
composer.json version spec).
This is pretty simple. However, there’s also this
composer.lock file that gets generated at the root of your repository. Why? And what should you do with it?
Do You Know Where Your Lock File Is?
A few weeks ago on Twitter, I noticed that the OpenCFP project doesn’t have a
composer.lock file in it’s repository. “So what,” you might say, “just
composer install and away you go. You’ll get the same dependencies, right?”
The point of the lock file is to record the exact versions that are installed so they can be re-installed. This means that if you have a version spec of
1.* and your co-worker runs
composer update which installs 1.2.4, and then commits the
composer.lock file, when you
composer install, you will also get 1.2.4, even if 1.3.0 has been released. This ensures everybody working on the project has the same exact version.
Now, you might be thinking: with proper semantic versioning, 1.3.0 (or even 1.2.5) should be backwards compatible because it still conforms to the
1.* version spec, i.e. the major version number hasn’t changed. So what’s the big deal?
Well, unless you are performing code reviews on every release of every dependency, and their dependencies, and so on and so forth, it’s highly likely that some sort of bug or change will creep in eventually that will break your code. We’re only human, after all.
It’s also pretty common for a project to set a dependency version to rely on dev-master, meaning they pull the most recent changes each time. This means that if anything has been committed since the last time a
composer install was done, then, without a lock file, you will get new third-party code being pulled down.
Again, this is a problem if you’re concerned about your code breaking. And it’s one of the reasons why it’s important to think about Composer as being centered around the
composer.lock file. It is a safety device, and should be used like one.
Install or Update?
People often get confused as to whether they should
update. Once you start to think about them as acting upon the lock file instead of the dependencies, things become much easier to think about.
composer install will:
- Check if a
- If not, perform a
composer updateto create one
composer.lockexists, install the specified versions from the lock file
composer update will:
- Determine the latest versions to install based on your version specs
- Install the latest versions
composer.lockto reflect the latest versions installed
Either way, after running one of these commands, you should commit the
composer.lock to your version control system to ensure all your collaborators areon the same page.
There is one exception to the rule. In the case of something like the Zend Framework 2 Skeleton App, the dependencies should update when you install. That’s because the Skeleton App is a meta-app. So you want to grab the latest dependencies from which to start developing. Therefore the
composer.lock is not committed to the repo.
composer.lock in your repository you should
composer install when deploying. This ensures the same dependencies are used in production as in development. It also means composer doesn’t need to do dependency resolution and version lookups, improving deployment performance.
composer.lock file also ensures consistency across clusters of servers, if you’re running Composer separately on each machine. It enables you to spin up new instances weeks, or months later, without being concerned about dependency mismatch.
So you see, it’s all about the lock file. If you ever wonder whether to call
composer install, or
composer update, let the lock file guide you. If you associate these commands with how they apply to the content of the lock file (and not the dependencies themselves) you can’t go wrong.
In short, if you ever wonder if you should commit the
composer.lock to version control, the answer is: YES.
P.S. If you haven’t been committing your lock file to revision control: why not? Will you switch to doing so now? We’d love to hear your thoughts!