But I Already Know Composer
I know that a series on Composer might seem odd. But, as Composer’s been a part of PHP for so long now, I feel that it’s something which most of us take for granted.
It’s revolutionised the PHP landscape, making it easier than ever before to build great software in PHP. But do we really know how to get the most out of it. For that reason, I’ve created this series, so that you level up your skills and really get the most from it.
In part one of this series, I’m going to take you through Composer’s command-line. I’ve cherry-picked a key subset of the command-line options, and focused in on key switches, so that you can do more than you already can.
I’ve decided to skip
require, as they’ve been covered copious times before. Sorry to disappoint if that’s what you were expecting.
We’re going to start off with the create-project option. This one I didn’t know about for the longest time. But when I did, I was more than excited to start using. If you’re not familiar with it, you’re probably used to doing the following:
git clone your_package_uri your/project/directory/path
The create-project command does all this for you. Say that you’re creating an application based on Zend Expressive and it’s going to be in a directory called
expressive-demo-app in the current directory. Here’s how you would do it with the create-project command:
composer create-project -s rc zendframework/zend-expressive-skeleton expressive-demo-app
Note that I’ve passed the
-s switch, with
rc as a parameter to that. This indicates the minimum-stability level allowed. We could also have passed a number of others.
We could specify a working directory, other than the current one, using the
--working-directory switch. This can be helpful if you’re scripting up the process — or you just don’t want to
cd somewhere, then
cd back again.
We could avoid the package scripts running by passing the
--no-scripts switch. We could prevent Composer’s output progress indicator from running, if that causes issues with the script we’re using to automate the process, by passing the
Interestingly, we can also prevent installation of the packages dependencies, by passing the
This is, I find, a very interesting and helpful command. Sure, you can open up
composer.json, but that’s not a scriptable process. So, instead use the
show command. This, as the name implies, shows a host of information about installed and configured packages.
It provides the ability to list the installed packages, list information about the current package (your composer.json configuration), and more.
Ok, let’s say I’m curious, and want to know the names of the currently installed packages for my application. To do that, I’d run the following command:
composer show -N # I could also pass the --name-only switch
This will print a sorted list of the names of the currently installed packages, similar to this:
How about getting a list of all the installed packages, with all their details? To do that, we’d instead pass either the
--installed switches. Doing that will show a listing similar to this:
zendframework/zend-loader 2.6.x-dev dcacfc3
zendframework/zend-servicemanager 3.2.x-dev 6ed63fd
zendframework/zend-stdlib 3.2.x-dev 16818ed
Here, you see the name of the package along with its installed version, and the git commit hash. As there’s quite some overlap with the
outdated command, which we cover later. So I’ll leave a more in-depth coverage of some of the commands until then.
Now what if I wanted to know all of the dependencies of the installed packages, whether that was another package or a PHP extension? This can be handy if you’re wondering why a package is installed, or just what it requires, without plumbing through copious composer.json files.
To do that, we’d pass the
--tree switch, which would give us output similar to this:
──symfony/browser-kit >=2.7 <4.0
│ ├──php >=5.5.9
│ └──symfony/dom-crawler ~2.8|~3.0
│ ├──php >=5.5.9
│ └──symfony/polyfill-mbstring ~1.0
│ └──php >=5.3.3
Here, you can see that symfony/browser-kit requires php 5.5.9 (or higher) and symfony/dom-crawler. Symfony/dom-crawler requires PHP 5.5.9, and symfony/polyfill-mbstring, and so on. Sometimes it’s hard to quickly find out what’s requiring what. This command can save you a lot of time.
What if I wanted to know about the current package. To do that, I could pass the
--self switches, which for my application, would return the following:
name : settermjd/zend-expressive-auth
descrip. : This package provides HTML-based authentication middleware for Zend Expressive applications
versions : * dev-create-rest-authentication-class
type : project
license : BSD 3-clause "New" or "Revised" License (BSD-3-Clause) (OSI approved) https://spdx.org/licenses/BSD-3-Clause.html#licenseText
source :  9d62baa0975a5ddd779dd942b5494a73ec59cd4c
dist :  9d62baa0975a5ddd779dd942b5494a73ec59cd4c
names : settermjd/zend-expressive-auth
App\ => src/App/
php ^5.5 || ^7.0
zendframework/zend-servicemanager ^2.7.3 || ^3.0
zendframework/zend-stdlib ^2.7 || ^3.0
filp/whoops ^1.1 || ^2.0
Here, you can see that it prints out the package meta data, followed by the configured autoloader namespaces, followed by the production and development dependencies.
We’ve seen in require and install how to add packages to a package. So it’s great that there’s an inverse command — remove. Remove, as the name implies, removes packages from your
composer.json and then runs an update to remove the physical dependency (and in turn their dependencies) from your vendor directory.
As with install and update, remove can remove one or many packages simultaneously. So, say I had zendframework/zend-stdlib and sandrokeil/interop-config as dependencies. Here’s an example of how I could remove just one, or both, of them:
// remove just one package
composer remove zendframework/zend-stdlib
// remove multiple packages at once
composer remove zendframework/zend-stdlib sandrokeil/interop-config
By default this only affects non-dev packages. So if you want to change development dependencies instead, then pass the
--dev switch as well.
Now as Composer’s used in a range of situations, from setup to deployment some of the default actions may or may not be desirable. So, it’s good to know that you can customize the process a little, to suit your needs.
If you don’t need to remove the dependency, then pass the
--no-update switch. If progress output would be a problem in your scripts, or you simply don’t want it, then pass the
--no-progress switch. If you don’t want any of the scripts defined for the package to run, then pass the
Ever tried to install a new package in an existing repository, but Composer’s not let you, complaining of a conflict? Perhaps you’ve seen output similar to that below and shaken your head, wondering how to fix it.
Your requirements could not be resolved to an installable set of packages.
- Conclusion: don't install mcustiel/phiremock-codeception-extension v1.2.1
- Conclusion: remove zendframework/zend-diactoros 1.4.x-dev
- Installation request for mcustiel/phiremock-codeception-extension ^1.2 -> satisfiable by mcustiel/phiremock-codeception-extension[v1.2.0, v1.2.1].
- Conclusion: don't install zendframework/zend-diactoros 1.4.x-dev
- mcustiel/phiremock-codeception-extension v1.2.0 requires mcustiel/phiremock ^1.1.0 -> satisfiable by mcustiel/phiremock[v1.1.0, v1.1.1, v1.1.2, v1.2.0, v1.2.1, v1.3.0, v1.3.1].
- mcustiel/phiremock v1.1.0 requires mcustiel/power-route ^2.0 -> satisfiable by mcustiel/power-route[v2.0.0, v2.1.0, v2.2.0].
- mcustiel/phiremock v1.1.1 requires mcustiel/power-route ^2.0 -> satisfiable by mcustiel/power-route[v2.0.0, v2.1.0, v2.2.0].
/* truncated for readability */
Installation failed, reverting ./composer.json to its original content.
Here, I tried to install
mcustiel/phiremock-codeception-extension, but one of its dependencies depends on a version
This is further complicated because another package depends on a higher version of
zend-diactoros. While the message helps debug the basics, it doesn’t help us track down the issue fully.
That’s where the
depends option comes to the rescue. To find out which package also depends on Zend-Diactoros, I can run the following command:
composer depends zendframework/zend-diactoros
This turned up the following:
zendframework/zend-expressive dev-develop requires zendframework/zend-diactoros (^1.1)
Here, we see that Zend Expressive is the package that requires Zend Diactoros. That’s great. But why? Well, let’s go find out, by using the
--recursive switch, recursively searches through the required packages and provides a path from the searched package through each successive package, showing all the packages which are involved. Here’s what it showed when I used the
settermjd/zend-expressive-auth rest-auth requires zendframework/zend-expressive (^1.0)
zendframework/zend-expressive dev-develop requires zendframework/zend-diactoros (^1.1)
Here, I see that my package, which I’m developing, requires Zend Expressive ^1.0, which in turn requires Zend Diactoros ^1.1. Great that I know that, but it isn’t the easiest to read.
While text is great for computers, I find it a lot easier to read when it has some colour and formatting. Turns out there’s a switch for that as well: the
--tree switch. But re-running depends with one of the two, we get the output below:
zendframework/zend-diactoros 1.4.x-dev PSR HTTP Message implementations
└──zendframework/zend-expressive dev-develop (requires zendframework/zend-diactoros ^1.1)
└──settermjd/zend-expressive-auth dev-create-rest-authentication-class (requires zendframework/zend-expressive ^1.0)
Here, we see the packages which require Zend Diactoros, but in a much more readable way. When I found this, I never looked back.
Want to know which packages which your application uses that are outdated? Then the aptly named outdated option is for you. While a proxy to
composer show -l it’s helpful in its own right.
Let’s run it in the package that I’ve been working on and see what it shows. I’ll run
composer outdated, and the result is below, which I’ve truncated for readability.
codeception/codeception 2.2.x-dev 08cbe80 dev-master c8df4d7 BDD-style testing framework
container-interop/container-interop 1.1.0 dev-master 8cbf8b1 Promoting the interoperability of container objects (DIC, SL...
While a little hard to read, it has the following format:
package name / installed version / latest installed commit / latest version / latest commit / package description
There’s a lot of information being shown. But it’s helpful if you really want to dig deep. To help out, the output of the latest version and commit hash, which you won’t see here, is color-coded.
If it’s green, you’re at the latest version. If it’s yellow, there’s an update available. If it’s red, there’s a new version available, which is semver-compatible, and you are advised to upgrade.
By default, you see everything, which isn’t always helpful. In my own case it was quite overwhelming. There are two switches which help us make sense of this; these are:
-DShow only packages that are outdated
-oShow only packages directly required by the root package (your application)
You know when you run
composer require you often see a message similar to “This package suggest package X”? These are a list of packages which the package maintainers suggest that you use, but don’t enforce you to. How often do you pay attention to these?
How often do you wonder what they were, and want to find them quickly and easily? Sure, you can look through all the composer.json files, to find this out. But that’s tedious. The
suggests command does it all for you.
composer suggests in my own repository, it suggested a large list, which includes the following:
As well as the other packages, they were printed out as you see them listed above. No duplicates, and sorted in alphabetical order for readability. How long would it take you to go through all the composer.json files and do that by hand, or to create a script to do it for you? Arguably, too long!
Perhaps though you’re not interested in every suggestion. Perhaps you’re just interested in the suggestions for a specific package, such as Zend Expressive. If that’s the case, then include that package (or those packages), like this:
composer suggests zendframework/zend-expressive
Want to know why packages were suggested? There’s a switch for that. It’s the
--by-suggestion switch. By adding it to the previous command, I’m shown the following output:
aura/di is suggested by:
- zendframework/zend-expressive: 3.0.*@beta to make use of Aura.Di dependency injection container
filp/whoops is suggested by:
- zendframework/zend-expressive: ^2.0 to use the Whoops error handler
xtreamwayz/pimple-container-interop is suggested by:
- zendframework/zend-expressive: ^1.0 to use Pimple for dependency injection
There, you can see each of the suggested packages, and why they were suggested. That makes it explicitly clear. Now you know why you would use them, and when.
In Conclusion (tl;dr)
Those were nine of Composer’s key commands, along with a series of command switches; ones which should help you make even better use of Composer than you already do.
In the second part of the series you’ll learn how to automate projects using Composer scripts. And in the third and final part of the series, you’ll learn how to use forked repositories with Composer.
If you want to know more, I strongly encourage you to check out the command-line section of the Composer manual. It’s filled with a wealth of great information.
Didn’t like my command choices and switches? Which ones would you have chosen? And why?