Semantic Versioning library for PHP. It implements the full semantic version 2.0.0 specification and provides ability to parse, compare, and increment semantic versions along with validation against constraints.
| Version | PHP Version |
|---|---|
>=1.0, <1.2 |
>=5.5 |
>=1.2, <3.0 |
>=7.1 |
>=3.0 |
>=8.1 |
composer require z4kn4fein/php-semver
The following options are supported to construct a Version:
Building part by part with Version::create().
Version::create(3, 5, 2, "alpha", "build");
Parsing from a string with Version::parse() or Version::parseOrNull().
Version::parse("3.5.2-alpha+build");
The following information is accessible on a constructed Version object:
<?php
use z4kn4fein\SemVer\Version;
$version = Version::parse("2.5.6-alpha.12+build.34");
echo $version->getMajor(); // 2
echo $version->getMinor(); // 5
echo $version->getPatch(); // 6
echo $version->getPreRelease(); // alpha.12
echo $version->getBuildMeta(); // build.34
echo $version->isPreRelease(); // true
echo $version->isStable(); // false
echo $version->withoutSuffixes(); // 2.5.6
echo $version; // 2.5.6-alpha.12+build.34
By default, the version parser considers partial versions like 1.0 and versions starting with the v prefix invalid.
This behaviour can be turned off by setting the strict parameter to false.
echo Version::parse("v2.3-alpha"); // exception
echo Version::parse("2.1"); // exception
echo Version::parse("v3"); // exception
echo Version::parse("v2.3-alpha", false); // 2.3.0-alpha
echo Version::parse("2.1", false); // 2.1.0
echo Version::parse("v3", false); // 3.0.0
It is possible to compare two Version objects with the following comparison methods.
<?php
use z4kn4fein\SemVer\Version;
// with static methods
echo Version::lessThan("2.3.4", "2.4.1"); // true
echo Version::lessThanOrEqual("2.4.1", "2.4.1"); // true
echo Version::greaterThan("2.3.1-alpha.5", "2.3.1-alpha.3"); // true
echo Version::greaterThanOrEqual("3.2.3","3.2.2"); // true
echo Version::equal("3.2.3","3.2.3+build.3"); // true
echo Version::notEqual("3.2.3","2.2.4"); // true
// compare() or compareString()
echo Version::compare(Version::parse("2.3.4"), Version::parse("2.4.1")); // -1
echo Version::compare(Version::parse("2.3.4"), Version::parse("2.3.4")); // 0
echo Version::compare(Version::parse("2.3.4"), Version::parse("2.2.0")); // 1
echo Version::compareString("2.3.4", "2.4.1"); // -1
echo Version::compareString("2.3.4", "2.3.4"); // 0
echo Version::compareString("2.3.4", "2.2.0"); // 1
// with instance methods
$version = Version::parse("2.5.6-alpha.12+build.34");
echo $version->isLessThan(Version::parse("2.3.1")); // false
echo $version->isLessThanOrEqual(Version::parse("2.5.6-alpha.15")); // true
echo $version->isGreaterThan(Version::parse("2.5.6")); // false
echo $version->isLessThanOrEqual(Version::parse("2.5.6-alpha.12")); // true
echo $version->isEqual(Version::parse("2.5.6-alpha.12+build.56")); // true
echo $version->isNotEqual(Version::parse("2.2.4")); // true
Version::sort() and Version::sortString() are available to sort an array of versions.
<?php
use z4kn4fein\SemVer\Version;
$versions = array_map(function(string $version) {
return Version::parse($version);
}, [
"1.0.1",
"1.0.1-alpha",
"1.0.1-alpha.beta",
"1.0.1-alpha.3",
"1.0.1-alpha.2",
"1.1.0",
"1.1.0+build",
]);
$sorted = Version::sort($versions);
// The result:
// "1.0.1-alpha"
// "1.0.1-alpha.2"
// "1.0.1-alpha.3"
// "1.0.1-alpha.beta"
// "1.0.1"
// "1.1.0"
// "1.1.0+build"
You might want to sort in reverse order, then you can use Version::rsort() or Version::rsortString().
<?php
use z4kn4fein\SemVer\Version;
$versions = array_map(function(string $version) {
return Version::parse($version);
}, [
"1.0.1",
"1.0.1-alpha",
"1.0.1-alpha.beta",
"1.0.1-alpha.3",
"1.0.1-alpha.2",
"1.1.0",
"1.1.0+build",
]);
$sorted = Version::rsort($versions);
// The result:
// "1.1.0"
// "1.1.0+build"
// "1.0.1"
// "1.0.1-alpha.beta"
// "1.0.1-alpha.3"
// "1.0.1-alpha.2"
// "1.0.1-alpha"
Version::compare() and Version::compareString() methods also can be used as callback for usort() to sort an array of versions.
<?php
use z4kn4fein\SemVer\Version;
$versions = array_map(function(string $version) {
return Version::parse($version);
}, [
"1.0.1",
"1.0.1-alpha",
"1.0.1-alpha.beta",
"1.0.1-alpha.3",
"1.0.1-alpha.2",
"1.1.0",
"1.1.0+build",
]);
usort($versions, ["z4kn4fein\SemVer\Version", "compare"]);
// The result:
// "1.0.1-alpha"
// "1.0.1-alpha.2"
// "1.0.1-alpha.3"
// "1.0.1-alpha.beta"
// "1.0.1"
// "1.1.0"
// "1.1.0+build"
With constraints, it's possible to validate whether a version satisfies a set of rules or not.
A constraint can be described as one or more conditions combined with logical OR and AND operators.
Conditions are usually composed of a comparison operator and a version like >=1.2.0.
The condition >=1.2.0 would be met by any version that greater than or equal to 1.2.0.
Supported comparison operators:
= Equal (equivalent to no operator: 1.2.0 means =1.2.0)!= Not equal< Less than<= Less than or equal> Greater than>= Greater than or equalConditions can be joined together with whitespace, representing the AND logical operator between them.
The OR operator can be expressed with || or | between condition sets.
For example, the constraint >=1.2.0 <3.0.0 || >4.0.0 translates to: Only those versions are allowed that are either greater than or
equal to 1.2.0 {AND} less than 3.0.0 {OR} greater than 4.0.0.
We can notice that the first part of the previous constraint (>=1.2.0 <3.0.0) is a simple semantic version range.
There are more ways to express version ranges; the following section will go through all the available options.
There are particular range indicators which are sugars for more extended range expressions.
X-Range: The x, X, and * characters can be used as a wildcard for the numeric parts of a version.
1.2.x translates to >=1.2.0 <1.3.0-01.x translates to >=1.0.0 <2.0.0-0* translates to >=0.0.0In partial version expressions, the missing numbers are treated as wildcards.
1.2 means 1.2.x which finally translates to >=1.2.0 <1.3.0-01 means 1.x or 1.x.x which finally translates to >=1.0.0 <2.0.0-0Hyphen Range: Describes an inclusive version range. Wildcards are evaluated and taken into account in the final range.
1.0.0 - 1.2.0 translates to >=1.0.0 <=1.2.01.1 - 1.4.0 means >=(>=1.1.0 <1.2.0-0) <=1.4.0 which finally translates to >=1.1.0 <=1.4.01.1.0 - 2 means >=1.1.0 <=(>=2.0.0 <3.0.0-0) which finally translates to >=1.1.0 <3.0.0-0Tilde Range (~): Describes a patch level range when the minor version is specified or a minor level range when it's not.
~1.0.1 translates to >=1.0.1 <1.1.0-0~1.0 translates to >=1.0.0 <1.1.0-0~1 translates to >=1.0.0 <2.0.0-0~1.0.0-alpha.1 translates to >=1.0.1-alpha.1 <1.1.0-0Caret Range (^): Describes a range with regard to the most left non-zero part of the version.
^1.1.2 translates to >=1.1.2 <2.0.0-0^0.1.2 translates to >=0.1.2 <0.2.0-0^0.0.2 translates to >=0.0.2 <0.0.3-0^1.2 translates to >=1.2.0 <2.0.0-0^1 translates to >=1.0.0 <2.0.0-0^0.1.2-alpha.1 translates to >=0.1.2-alpha.1 <0.2.0-0Let's see how we can determine whether a version satisfies a constraint or not.
<?php
use z4kn4fein\SemVer\Version;
use z4kn4fein\SemVer\Constraints\Constraint;
$constraint = Constraint::parse(">=1.2.0");
$version = Version::parse("1.2.1");
echo $version->isSatisfying($constraint); // true
echo $constraint->isSatisfiedBy($version); // true
// Or using the static satisfies() method with strings:
echo Version::satisfies("1.2.1", ">=1.2.0"); // true
Version objects can produce incremented versions of themselves with the getNext{Major|Minor|Patch|PreRelease}Version methods.
These methods can be used to determine the next version in order incremented by the according part.
Version objects are immutable, so each incrementing function creates a new Version.
This example shows how the incrementation works on a stable version:
<?php
use z4kn4fein\SemVer\Version;
use z4kn4fein\SemVer\Inc;
$stableVersion = Version::create(1, 0, 0);
echo $stableVersion->getNextMajorVersion(); // 2.0.0
echo $stableVersion->getNextMinorVersion(); // 1.1.0
echo $stableVersion->getNextPatchVersion(); // 1.0.1
echo $stableVersion->getNextPreReleaseVersion(); // 1.0.1-0
// or with the inc() method:
echo $stableVersion->inc(Inc::MAJOR); // 2.0.0
echo $stableVersion->inc(Inc::MINOR); // 1.1.0
echo $stableVersion->inc(Inc::PATCH); // 1.0.1
echo $stableVersion->inc(Inc::PRE_RELEASE); // 1.0.1-0
In case of an unstable version:
<?php
use z4kn4fein\SemVer\Version;
use z4kn4fein\SemVer\Inc;
$unstableVersion = Version::parse("1.0.0-alpha.2+build.1");
echo $unstableVersion->getNextMajorVersion(); // 2.0.0
echo $unstableVersion->getNextMinorVersion(); // 1.1.0
echo $unstableVersion->getNextPatchVersion(); // 1.0.0
echo $unstableVersion->getNextPreReleaseVersion(); // 1.0.0-alpha.3
// or with the inc() method:
echo $unstableVersion->inc(Inc::MAJOR); // 2.0.0
echo $unstableVersion->inc(Inc::MINOR); // 1.1.0
echo $unstableVersion->inc(Inc::PATCH); // 1.0.0
echo $unstableVersion->inc(Inc::PRE_RELEASE); // 1.0.0-alpha.3
Each incrementing function provides the option to set a pre-release identity on the incremented version.
<?php
use z4kn4fein\SemVer\Version;
use z4kn4fein\SemVer\Inc;
$version = Version::parse("1.0.0-alpha.1");
echo $version->getNextMajorVersion("beta"); // 2.0.0-beta
echo $version->getNextMinorVersion(""); // 1.1.0-0
echo $version->getNextPatchVersion("alpha"); // 1.0.1-alpha
echo $version->getNextPreReleaseVersion("alpha"); // 1.0.0-alpha.2
// or with the inc() method:
echo $version->inc(Inc::MAJOR, "beta"); // 2.0.0-beta
echo $version->inc(Inc::MINOR, ""); // 1.1.0-0
echo $version->inc(Inc::PATCH, "alpha"); // 1.0.1-alpha
echo $version->inc(Inc::PRE_RELEASE, "alpha"); // 1.0.0-alpha.2
It's possible to make a copy of a particular version with the copy() method.
It allows altering the copied version's properties with optional parameters.
$version = Version::parse("1.0.0-alpha.2+build.1");
echo $version->copy(); // 1.0.0-alpha.2+build.1
echo $version->copy(3); // 3.0.0-alpha.2+build.1
echo $version->copy(null, 4); // 1.4.0-alpha.2+build.1
echo $version->copy(null, null, 5); // 1.0.5-alpha.2+build.1
echo $version->copy(null, null, null, "alpha.4"); // 1.0.0-alpha.4+build.1
echo $version->copy(null, null, null, null, "build.3"); // 1.0.0-alpha.2+build.3
echo $version->copy(3, 4, 5); // 3.4.5-alpha.2+build.1
[!NOTE]
Without setting any optional parameter, thecopy()method will produce an exact copy of the original version.
When the version or constraint parsing fails due to an invalid format, the library throws a specific SemverException.
[!NOTE]
TheVersion::parseOrNull()andConstraint::parseOrNull()methods can be used for exception-less conversions as they returnnullwhen the parsing fails.
How can I help you explore Laravel packages today?