Composer: It’s All About the Lock File

Composer: It’s All About the Lock File

Composer is the defacto standard for package management in PHP. It’s simple, effective, and has become ubiquitous in the community.

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?”

Wrong.

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 install or 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.

Running composer install will:

  • Check if a composer.lock exists
  • If not, perform a composer update to create one
  • If composer.lock exists, install the specified versions from the lock file

Running composer update will:

  • Check composer.json
  • Determine the latest versions to install based on your version specs
  • Install the latest versions
  • Update composer.lock to 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.

Deployment

With the 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.

Having a 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.

Conclusion

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!

About Davey Shafik

Davey Shafik is a full time PHP Developer with 12 years experience in PHP and related technologies. A Community Engineer for Engine Yard, he has written three books (so far!), numerous articles and spoken at conferences the globe over.

Davey is best known for his books, the Zend PHP 5 Certification Study Guide and PHP Master: Write Cutting Edge Code, and as the originator of PHP Archive (PHAR) for PHP 5.3.