version_compare

Compares two PHP-style version number strings and reports which one is newer.

Signature
version_compare(string $version1, string $version2, ?string $operator = null): int|bool
  • Added in PHP 4.1.0

Parameters

ParameterTypeDescription
$version1stringThe first version string to compare.
$version2stringThe second version string to compare.
$operatoroptional?string= nullAn optional comparison operator: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <> or ne. Operators are case sensitive and should be lowercase.

Return value

int|boolWithout an operator, returns -1 when version1 is lower, 0 when the two are equal, and 1 when version1 is higher. With an operator, returns true or false depending on whether the comparison holds.

Errors

Does not throw. Supplying an operator that is not in the documented list makes the function return null rather than a bool.

Version numbers are not numbers. 1.10 is newer than 1.9, but a string or float comparison says the opposite. version_compare() normalises both strings and compares them segment by segment the way a release manager would.

How the strings are normalised

PHP replaces _, - and + with a dot, then inserts dots around every run of non-digits, so 4.3.2RC1 becomes 4.3.2.RC.1. The parts are then compared left to right. Numeric parts compare numerically; textual parts use this fixed ranking:

any unrecognised string < dev < alpha = a < beta = b < RC = rc < # < pl = p

That ranking is why 1.0.0-beta correctly sorts below 1.0.0, and why a made-up suffix such as 1.0.0-nightly sorts below 1.0.0-dev — unrecognised strings are the lowest rank of all.

When to reach for it

Use it for minimum-version gates in plugins and libraries, for deciding whether an update is available, and as the callback body when sorting a list of releases with usort(). For comparing PHP itself, prefer the PHP_VERSION_ID integer constant in hot paths — it is a plain integer compare — and keep version_compare() for third-party version strings whose shape you do not control.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Refuse to boot a library when the host PHP is older than the minimum it supports.
  • Decide whether a package's installed version is behind the latest published release.
  • Sort a list of release tags such as 2.0.0-rc1, 2.0.0 and 2.0.1 into true release order.

Frequently asked questions

Does version_compare support semantic versioning?

It handles the common semver shapes correctly, including pre-release suffixes such as -alpha, -beta and -rc, because it maps those keywords onto its own ranking. It does not implement the full semver spec: build metadata after + is treated as another version segment rather than being ignored, and unknown pre-release words all collapse to the lowest rank.

Why does version_compare('1.0', '1.0.0') return -1 instead of 0?

Because the two strings have a different number of segments and PHP does not pad the shorter one with zeros. It compares part by part and treats the missing third part as lower. Pad both versions to the same length yourself if you want them to be equal.

What is the difference between version_compare and PHP_VERSION_ID?

PHP_VERSION_ID is a plain integer such as 80510 that you compare with normal operators, and it is faster and unambiguous for checking the running PHP version. version_compare parses arbitrary version strings, so use it for library, package or API versions whose format you do not control.

More examples

Gate a feature on a minimum version

The three-argument form returns a bool, so it reads like a condition. 8.5.10 and 8.1.0 both pass the >= 8.1.0 gate; 8.0.30 fails, and note that the check is a real numeric comparison, so 8.0.30 is not mistaken for being above 8.1.0.

Example · php
<?php

function supportsFeature(string $installed): string
{
    if (version_compare($installed, '8.1.0', '<')) {
        return "Upgrade required (found {$installed}, need 8.1.0+)";
    }
    return "OK on {$installed}";
}

echo supportsFeature('8.5.10'), "\n";
echo supportsFeature('8.0.30'), "\n";
echo supportsFeature('8.1.0'), "\n";

Pre-release suffixes and the ranking order

Every line prints -1, confirming the documented order dev < alpha < beta < rc < release < pl. The last line shows the trap: nightly is not a keyword PHP knows, so it ranks below even dev.

Example · php
<?php

$pairs = [
    ['1.0.0-dev',    '1.0.0-alpha'],
    ['1.0.0-alpha',  '1.0.0-beta'],
    ['1.0.0-beta',   '1.0.0-rc1'],
    ['1.0.0-rc1',    '1.0.0'],
    ['1.0.0',        '1.0.0-pl1'],
    ['1.0.0-nightly','1.0.0-dev'],
];

foreach ($pairs as [$a, $b]) {
    printf("%-16s vs %-14s => %d\n", $a, $b, version_compare($a, $b));
}

Length mismatch and zero padding

The first call reports 1.0 as older than 1.0.0 because it has one fewer segment. Padding both strings to the same number of segments first makes them compare equal, which is usually what you meant.

Example · php
<?php

var_dump(version_compare('1.0', '1.0.0'));   // int(-1)

function normalise(string $v, int $parts = 3): string
{
    $bits = array_pad(explode('.', $v), $parts, '0');
    return implode('.', array_slice($bits, 0, $parts));
}

var_dump(version_compare(normalise('1.0'), normalise('1.0.0'))); // int(0)

Discussion

  • Be the first to comment on this lesson.