# Nine things you need to remember when using Composer
When I started using Composer (opens new window) I hardly noticed I was using it until it gave me problems. Now that I've used Laravel for a while, I'm realising how much I've been neglecting Composer! Composer can be super handy and easy to use once you've learned a few of its tricks. Here are a few of the things that help me work more effectively with Composer:
# 1. Remember the difference between composer install
and composer update
This is probably the most important concept you need to understand about Composer. On the surface composer install
and composer update
look very similar. Both can modify the packages and/or their versions in your vendor
folder. However, they have some subtle though very important differences. Here are three different explanations to help you remember their differences:
# 1.1 TLDR 1
Run composer install
when you first create or clone a project, after you've switched to another branch or pulled changes from a remote. Run composer update
when you want to install new requirements or update your current dependencies to their latest available versions.
# 1.2 TLDR 2
Run composer install
when your composer.lock
file has changed or when you don't have a composer.lock
file. Run composer update
when the composer.json
file has changed or when you want to update your dependencies to their latest available versions.
# 1.3 Longer explanation
composer install
lets you install your initial set of dependencies when no composer.lock
file exists. It uses your composer.json
file to resolve a set of compatible package versions and installs them into the vendor
directory. It will create a composer.lock
file which would contain the exact package versions that it has installed.
When the composer.lock
file exists, composer install
ignores the composer.json
file and simply installs the exact same packages and versions that the file contains. Even if your composer.json
file contains new package dependencies Composer will ignore them. That is where composer update
comes in...
composer update
basically does the same that composer install
did when there were no composer.lock
file yet. In fact, this block in the Composer source (opens new window) shows us that it is actually an "update" that is being done when no composer.lock
file exists:
// Force update if there is no lock file present
if (!$this->update && !$this->locker->isLocked()) {
$this->update = true;
}
2
3
4
5
composer update
will look at your composer.json
file again and resolve the latest versions of all the package requirements, install them to your vendor
folder and overwrite your composer.lock
file. If you've removed any package dependencies from your composer.json
it will uninstall them.
One last thing: composer upgrade
is just an alias for composer update
, so you don't need to worry about it if you know composer update
.
# 2. Never run Composer as sudo/root
Some composer packages contains scripts that Composer will run, and if you run Composer as sudo these scripts can do anything that you can do as a sudo user. Scary stuff!
Even though Composer shows a warning when you try to run composer as root and has a dedicated FAQ page (opens new window) about it, many people (including my former self!) run composer as root. Unfortunately that FAQ page doesn't tell noobs like me how to not run it as root, but luckily there's this (opens new window) really great blog post on how stop running Composer as root.
# 3. Packagist (opens new window) is a better place to find packages than Google
I used to use Google to find php packages for my projects, but once I found Packagist, I never looked back. Packagist (opens new window) is the main repository for Composer packages and unless you're using internal company packages, all of your Composer packages would probably be downloaded from Packagist (even if you don't know about it!). Packagist's search functionality isn't half bad and using it to find packages is much more effective than using an ordinary search engine.
Simply search for keywords and Packagist will show you matching packages. The search listings make it easy for you to see how many times each package has been installed. Clicking on a search result takes you to the package's page where you can see it's dependencies, README file, available releases and link to it's source repository.
# 4. Never modify anything inside the vendor
folder
If you edit anything in your vendor
directory your edits will be overwritten the next time you run composer update
. If you want modify a package (which I highly encourage for learning and contributing purposes!) rather create a fork of the package's repository and make your changes on a new branch. To find the package's repository, simply type composer home vendor/package-name
in your console. You can add your forked repository as a "repository" (opens new window) in your composer.json
file and you can use your branch as the package's version requirement. That way your team mates can also use your modified version of the package. To install your package, simply run composer update
.
If you later create a pull request from your branch to the package's main repository and it gets merged, you can simply change the version requirement for the package in your composer.json
file back to the package's latest version. Have a look at this StackOverflow question (opens new window) for an example of a scenario like this.
# 5. You should (almost) always run composer install
after changing to another branch or pulling from a remote branch
When you switch branches or pull from a remote branch there's a chance that the composer.lock
file your getting is different from the one you had before. To ensure that your environment is in the same state that the environment on which the commit you checked out was tested on, you need to run composer install
. Luckily git hooks (opens new window) can do that for us automatically whenever the composer.lock
file has changed.
To check for changes to the composer.lock
file and run composer install
when you switch branches, simply copy and paste the following code (that I modified from this gist (opens new window)) to a new file called post-merge
in your .git/hooks
directory in your project:
changed_files="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"
check_run() {
echo "$changed_files" | grep -E --quiet "$1" && eval "$2"
}
check_run composer.lock 'printf "\nRunning composer install...\n\n" && composer install'
2
3
4
5
6
7
Then run chmod +x .git/hooks/post-merge
to make the file executable.
You can copy the following code to .git/hooks/post-checkout
and make it executable:
changed_files="$(git diff-tree -r --name-only --no-commit-id $1 $2)"
check_run() {
echo "$changed_files" | grep -E --quiet "$1" && eval "$2"
}
check_run composer.lock 'printf "\nRunning composer install...\n\n" && composer install'
2
3
4
5
6
7
# 6. Always commit your composer.lock
file
Often when your composer.lock
file has changed it means that you're using a new package that your code now relies on. If you don't commit your composer.lock
file your code might break on your team mates' environments!
# 7. composer require
might not always be your friend
composer require vendor/package
can be handy when you have to add and install a new dependency to your package. It removes the need for you to manually update your composer.json
file and to then run composer update
. It even allows you to add multiple packages at once with composer require vendor1/package1 vendor2/package2 etc.
. However, sometimes it will tell you that there aren't an available set of packages available when in fact there is.
It isn't exactly Composer's fault that it tells you this, because if you don't specify a version constraint for the package (using composer require vendor/package:version-constraint
) it assumes your want the latest minor version. But sometimes the latest versions aren't what you need and a noob like me didn't know that Composer won't be able to figure that out itself.
Let's have a look at this (opens new window) question on StackOverflow. The OP wanted to install the mailgun/mailgun-php
, php-http/curl-client
and guzzlehttp/psr7
packages. While there were a set of mutually compatible versions of the packages available (mailgun/mailgun-php:2.8.1
, php-http/curl-client:v1.7.1
and guzzlehttp/psr7:1.5.2
), composer require
failed and told him "Your requirements could not be resolved to an installable set of packages." composer require
tried to install the latest minor versions of each of the packages which was mailgun/mailgun-php:^2.8
, php-http/curl-client:^2.0
and guzzlehttp/psr7:^1.5
.
Luckily he didn't have to go and manually find a compatible set of dependencies himself. He could specify the lowest versions he'd want like this composer require mailgun/mailgun-php:">0" php-http/curl-client:">0" guzzlehttp/psr7:">0"
and Composer would find the latest set of versions that would satisfy all of the dependencies.
# 8. Keep the Composer versions documentation (opens new window) close by to refresh your understanding of package version constraints
This Composer documentation on versions and constraints is very thorough and useful. The two operators that you will often see in composer.json
files, but which aren't very obvious to the untrained eye, is ~
(The tilde version range (opens new window)) and ^
(the caret version range (opens new window)).
The ^
specifies a range where the minimum version is the version specified and the highest allowed version if the next breaking update (in semantic versioning (opens new window) terms). For example ^2.1
allows versions >=2.1
up to <3.0.0
, and ^1.1.1
allows versions up to <2.0.0
.
The ~
operator is similar, but it basically looks at the last specified digit in the version and allows only it to go up, but not the digits before it. For example ~1.2
can go up to anything below 2.0.0
, but ~1.1.2
can only go up to anything below 1.2
.
# 9. Lastly, run composer self-update
once in a while
composer self-update
is a handy command that updates your Composer installation itself and allows you to use the newest, shiniest version of Composer.
Newsletter
If you'd like to subscribe to my blog, please enter your details below. You can unsubscribe at any time.