Note: this is a repost from my post on the madewithlove blog.
When installing a dependency we are used to install a version that adheres to a known public interface and does what it promises. That way we can safely use it in our code.
A dependency that uses semantic versioning allows you to predict wether it is still going to work or not
when you upgrade it to a new version. Basically when the
x in a
x.y.z version number changes,
you might need to do some changes to be able to work with this new version without problems.
When dealing with a
0.y.z version this is slightly different: when the first non-zero number (
backwards compatibility is not guaranteed. If you’re not familiar with semver:
head over to the specs!
A dependency can change without breaking backwards compatibility. A new release will then have a greater version number (x.y), depending on the type of change (bugfix or added functionality). When you depend on packages you might want to define a range of versions that are OK to install, rather than having a locked down version specified. This allows you to receive fixes (that includes security fixes) from external code for free with a simple update command.
Depending on your dependency manager you can define version contraints using wildcards (
*), comparators like
logical operators (
, often means AND and
| means OR), etc… Using logical operators you can mix and match
different version constraints to build even more complex ones. For example
means everything that matches
0.10.*, but can also be noted as
0.9.* || 0.10.*.
There are also some syntactic sugar operators like
~ (tilde) and
The caret sign is slightly different:
^4.1.3(most used) means
>=4.1.0,<5.0.0, same as
>=0.4.0,<0.5.0, this is different from
~0.4and is more useful for defining backwards compatible version ranges.
>=4.0.0,<5.0.0which is the same as
Basically use the caret sign to exclude early releases which contain known threats. For example if you need
a dependency which has functionality which got introduced in
2.1.x and version
2.1.1 fixes a bug which
was shipped with the
2.1.0 release. If that bug affected you or when it’s a security bug,
you will be able to exclude all earlier versions with
This way you can still benefit from all new backward compatible releases.
caret is Latin for “it lacks”, so you can remember this as “it (this version range) lacks
some early releases but it’s backwards compatible up to the next major release”.
For now when you run the command
composer require monolog/monolog it will still save
(at the time of writing) as the default version constraint in your composer.json file and not
This is to protect users who might not have updated their Composer to a version which can handle
^ constraints. Expect this to change in the coming weeks or months.
In case you didn’t notice yet, the links behind all these version constraints point to semver.mwl.be. We created this tool after Maxime posted a link to semver.npmjs.com in our madewithlove slack channel.
I won’t go into stability as it is out of the scope of this blog post, but I suggest you play around with
to see the effect of selecting