ScotlandPHP

version_compare

(PHP 4 >= 4.1.0, PHP 5, PHP 7)

version_compareふたつの "PHP 標準" バージョン番号文字列を比較する

説明

mixed version_compare ( string $version1 , string $version2 [, string $operator ] )

version_compare()は、ふたつの "PHP 標準" バージョン 番号文字列を比較します。

この関数はまず、バージョン文字列の _, -, + をドット . で置き換えます。 さらに、数値でない部分の前後にドット . を追加します。 例えば '4.3.2RC1' は '4.3.2.RC.1' となります。 次に、左から右へ 各部分を比較していきます。特殊な文字列が含まれている場合は以下の順で 並べ替えます: ここにないすべての文字列 < dev < alpha = a < beta = b < RC = rc < # < pl = p この方法により、'4.1' と '4.1.2' のようなバージョンの違いだけではなく PHP 固有の開発ステータスの違いも判断することが可能となります。

パラメータ

version1

最初のバージョン番号。

version2

ふたつめのバージョン番号。

operator

三番目のオプション引数 operator を指定した場合、 特定の関係を調べることが可能です。指定可能な演算子を以下に示します。 <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne

このパラメータは大文字小文字を区別するので、すべて小文字で指定しなければなりません。

返り値

デフォルトでは、version_compare() の返り値は 最初のバージョンが 2 番目のバージョンより小さい場合に -1、 同じ場合に 0、そして 2 番目のバージョンのほうが小さい場合に 1 となります。

オプションの引数 operator を使用すると、 指定した演算子による関係を満たす場合に TRUE、それ以外の場合に FALSE を返すようになります。

以下の例では定数 PHP_VERSION を使用しています。 この定数には、コードを実行している PHP のバージョンが格納されています。

例1 version_compare() の例

<?php
if (version_compare(PHP_VERSION'7.0.0') >= 0) {
    echo 
'7.0.0 より新しいバージョンの PHP を使っています。バージョンは ' PHP_VERSION " です。\n";
}

if (
version_compare(PHP_VERSION'5.3.0') >= 0) {
    echo 
'5.3.0 より新しいバージョンの PHP を使っています。バージョンは ' PHP_VERSION " です。\n";
}

if (
version_compare(PHP_VERSION'5.0.0''>=')) {
    echo 
'5.0.0 より新しいバージョンの PHP を使っています。バージョンは ' PHP_VERSION " です。\n";
}

if (
version_compare(PHP_VERSION'5.0.0''<')) {
    echo 
'まだ PHP 4 です。バージョンは ' PHP_VERSION " です。\n";
}
?>

注意

注意:

PHP_VERSION 定数には現在の PHP のバージョンが格納されます。

注意:

プレリリース版 (たとえば 5.3.0-dev など) は、それに対応する正式版 (5.3.0) より小さいとみなされます。

注意:

alphabeta のようなバージョン文字列は、大文字小文字を区別します。 したがって、どこかから取得したバージョン文字列を PHP の標準に従わせるなら、 まず strtolower() で小文字化してから version_compare() を呼ぶ必要があります。

参考

  • phpversion() - 現在の PHP バージョンを取得する
  • php_uname() - PHP が稼動しているオペレーティングシステムに関する情報を返す
  • function_exists() - 指定した関数が定義されている場合に TRUE を返す

add a note add a note

User Contributed Notes 13 notes

up
16
eric at themepark dot com
13 years ago
[editors note]
snipbit fixed after comment from Matt Mullenweg

--jm
[/editors note]

so in a nutshell... I believe it works best like this:

<?php
if (version_compare(phpversion(), "4.3.0", ">=")) {
 
// you're on 4.3.0 or later
} else {
 
// you're not
}
?>
up
6
arnoud at procurios dot nl
13 years ago
If you're careful, this function actualy works quite nicely for comparing version numbers from programs other than PHP itself. I've used it to compare MySQL version numbers. The only issue is that version_compare doesn't recognize the 'gamma' addition that mysql uses as being later than 'alpha' or 'beta', because the latter two are treated specially. If you keep this in mind though, you should have no problems.
up
7
insid0r at yahoo dot com
8 years ago
Since this function considers 1 < 1.0 < 1.0.0, others might find this function useful (which considers 1 == 1.0):

<?php
//Compare two sets of versions, where major/minor/etc. releases are separated by dots.
//Returns 0 if both are equal, 1 if A > B, and -1 if B < A.
function version_compare2($a, $b)
{
   
$a = explode(".", rtrim($a, ".0")); //Split version into pieces and remove trailing .0
   
$b = explode(".", rtrim($b, ".0")); //Split version into pieces and remove trailing .0
   
foreach ($a as $depth => $aVal)
    {
//Iterate over each piece of A
       
if (isset($b[$depth]))
        {
//If B matches A to this depth, compare the values
           
if ($aVal > $b[$depth]) return 1; //Return A > B
           
else if ($aVal < $b[$depth]) return -1; //Return B > A
            //An equal result is inconclusive at this point
       
}
        else
        {
//If B does not match A to this depth, then A comes after B in sort order
           
return 1; //so return A > B
       
}
    }
   
//At this point, we know that to the depth that A and B extend to, they are equivalent.
    //Either the loop ended because A is shorter than B, or both are equal.
   
return (count($a) < count($b)) ? -1 : 0;
}
?>
up
6
rlerne at gmail dot com
2 years ago
What PHP.net page is any good without a classy userland implementation of a function already provided by PHP? Generally, there are pseudo-benchmarks and reasons why you'd want to use their "far superior" implementations.

Since exit is a difficult construct to implement, and exit cannot be called using variable functions, this function is <blink>BETTER</blink>.

While you cannot use this code without parentheses, you'll find that this exit function improves your site's performance with at least 25 teraflops of flux computing power!

I used to be a fan of die;, I even tried to use exit;, but now; I'm a true-blue userland_exit() fan, now with 20% more.*

*-Over the top competing brand.

<?php
function userland_exit($death_call=null)
    {
    if (
version_compare(PHP_VERSION,'4.2.0','<'))
        echo
$death_call;
    elseif  (!
is_int($death_call))
        echo
$death_call;
       
   
error_reporting(0);
   
trigger_error(null,E_USER_ERROR);
    }

userland_exit("I'm dead");
?>
up
3
mindplay.dk
5 years ago
This little script can perhaps help you understand version comparison a little better - the output is displayed in the comment at the top. Tweak the list of versions if you need more examples...

<?php

#      1 lt 1.0
#    1.0 lt 1.01
#   1.01 eq 1.1
#    1.1 lt 1.10
#   1.10 gt 1.10b
#  1.10b lt 1.10.0

header('Content-type: text/plain');

$versions = array(
 
'1',
 
'1.0',
 
'1.01',
 
'1.1',
 
'1.10',
 
'1.10b',
 
'1.10.0',
);

$comps = array(
-
1 => 'lt',
 
0 => 'eq',
 
1 => 'gt'
);

foreach (
$versions as $version) {
  if (isset(
$last)) {
   
$comp = version_compare($last, $version);
    echo
str_pad($last,8,' ',STR_PAD_LEFT) . " {$comps[$comp]} {$version}\n";
  }
 
$last = $version;
}

?>
up
3
opendb at iamvegan dot net
10 years ago
Something that may trip some folks up, but is useful to mention is that the following version comparison does not work quite as I expected:
    version_compare('1.0.1', '1.0pl1', '>')

However, its quite easy to get working:
    version_compare('1.0.1', '1.0.0pl1', '>')
up
1
rogier
5 years ago
Please note that supplying an operator that is not listed (e.g. ===), this function returns NULL instead of false.

Tested on PHP5.3.0, Win32
up
2
loaded67 at hotmail dot com
8 years ago
This function is also usefull when working with multiple installations.

As php5.3+ will not have E_STRICT in the error_reporting anymore you can state:

<?php
ini_set
('error_reporting', (version_compare(PHP_VERSION, '5.3.0', '<') ? E_ALL|E_STRICT : E_ALL));
?>

Giving you all the error error reporting you want...
up
1
sam at wyvern dot non-spammers-remove dot com dot au
13 years ago
Actually, it works to any degree:

<?php
version_compare
('1.2.3.4RC7.7', '1.2.3.4RC7.8')
version_compare('8.2.50.4', '8.2.52.6')
?>

will both give -1 (ie the left is lower than the right).
up
1
mina86 at tlen dot pl
13 years ago
Here's a wrapper which is more tolerant as far as order of arguments is considered:

<?php
function ver_cmp($arg1, $arg2 = null, $arg3 = null) {
  static
$phpversion = null;
  if (
$phpversion===null) $phpversion = phpversion();

  switch (
func_num_args()) {
  case
1: return version_compare($phpversion, $arg1);
  case
2:
    if (
preg_match('/^[lg][te]|[<>]=?|[!=]?=|eq|ne|<>$/i', $arg1))
      return
version_compare($phpversion, $arg2, $arg1);
    elseif (
preg_match('/^[lg][te]|[<>]=?|[!=]?=|eq|ne|<>$/i', $arg2))
      return
version_compare($phpversion, $arg1, $arg2);
    return
version_compare($arg1, $arg2);
  default:
   
$ver1 = $arg1;
    if (
preg_match('/^[lg][te]|[<>]=?|[!=]?=|eq|ne|<>$/i', $arg2))
      return
version_compare($arg1, $arg3, $arg2);
    return
version_compare($arg1, $arg2, $arg3);
  }
}
?>

It also uses phpversion() as a default version if only one string is present. It can make your code look nicer 'cuz you can now write:
<?php if (ver_cmp($version1, '>=', $version2)) something; ?>
and to check a version string against the PHP's version you might use:
<?php if (ver_cmp('>=', $version)) something; ?>
instead of using phpversion().
up
1
ivan maruca
11 months ago
function versionCompare($version1, $operator, $version2) {
   
    $_fv = intval ( trim ( str_replace ( '.', '', $version1 ) ) );
    $_sv = intval ( trim ( str_replace ( '.', '', $version2 ) ) );
   
    if (strlen ( $_fv ) > strlen ( $_sv )) {
        $_sv = str_pad ( $_sv, strlen ( $_fv ), 0 );
    }
   
    if (strlen ( $_fv ) < strlen ( $_sv )) {
        $_fv = str_pad ( $_fv, strlen ( $_sv ), 0 );
    }
   
    return version_compare ( ( string ) $_fv, ( string ) $_sv, $operator );
}

var_dump ( versionCompare ( '2.9', '<', '2.9.6' ) ); // true
var_dump ( versionCompare ( '2.9', '>', '2.9.6' ) ); // false
var_dump ( versionCompare ( '2.9', '<', '3.0' ) ); // true
var_dump ( versionCompare ( '2.9', '<=', '2.8.9' ) ); // false
var_dump ( versionCompare ( '2.9', '!=', '2.8.9' ) ); // true
var_dump ( versionCompare ( '2.8', '!=', '2.8.0' ) ); // false
var_dump ( versionCompare ( '2.9', '==', '2.9.0' ) ); // true
var_dump ( versionCompare ( '2.9', '==', '2.9.1' ) ); // false
var_dump ( versionCompare ( '3.0 beta', '>', '2.9.9' ) ); // true
up
1
Bob Ray
1 year ago
Note that both leading and trailing spaces on your version numbers can break version_compare().

Tested on PHP 5.6.8:
<?php
echo  "\nShould be 0";
echo
"\n '1.0.0-pl' vs. '1.0.0-pl'  ---> " . version_compare('1.0.0-pl', '1.0.0-pl');
echo
"\n '1.0.0-pl' vs. ' 1.0.0-pl' ---> " . version_compare('1.0.0-pl', ' 1.0.0-pl');
echo
"\n ' 1.0.0-pl' vs. '1.0.0-pl' ---> " . version_compare(' 1.0.0-pl', '1.0.0-pl');
echo
"\n '1.0.0-pl' vs. '1.0.0-pl ' ---> " . version_compare('1.0.0-pl', '1.0.0-pl ');
echo
"\n '1.0.0-pl ' vs. '1.0.0-pl' ---> " . version_compare('1.0.0-pl ', '1.0.0-pl');

echo
"\n\nShould be 1";
echo
"\n '1.1.1-pl' vs. '1.0.0-pl'  ---> " . version_compare('1.1.1-pl', '1.0.0-pl');
echo
"\n ' 1.1.1-pl' vs. '1.0.0-pl' ---> " . version_compare(' 1.1.1-pl', '1.0.0-pl');

echo
"\n\nShould be -1";
echo
"\n '1.0.0-pl' vs. '1.1.1-pl'  ---> " . version_compare('1.0.0-pl', '1.1.1-pl');
echo
"\n '1.0.0-pl' vs. ' 1.1.1-pl' ---> " . version_compare('1.0.0-pl', ' 1.1.1-pl');

   
/* Output
Should be 0
'1.0.0-pl' vs. '1.0.0-pl'  ---> 0
'1.0.0-pl' vs. ' 1.0.0-pl' ---> 1
' 1.0.0-pl' vs. '1.0.0-pl' ---> -1
'1.0.0-pl' vs. '1.0.0-pl ' ---> 1
'1.0.0-pl ' vs. '1.0.0-pl' ---> -1

Should be 1
'1.1.1-pl' vs. '1.0.0-pl'  ---> 1
' 1.1.1-pl' vs. '1.0.0-pl' ---> -1

Should be -1
'1.0.0-pl' vs. '1.1.1-pl'  ---> -1
'1.0.0-pl' vs. ' 1.1.1-pl' ---> 1
    */
up
0
Jonathon dot Reinhart at gmail dot com
9 years ago
I know this is somewhat incomplete, but it did a fair enough job for what I needed.  I was writing some code that needed done immediately on a server that was to be upgraded some time in the future.  Here is a quick replacement for version_compare (without the use of the operator argument). Feel free to add to this / complete it.

<?php
function version_compare2($version1, $version2)
{
   
$v1 = explode('.',$version1);
   
$v2 = explode('.',$version2);
   
    if (
$v1[0] > $v2[0])
       
$ret = 1;
    else if (
$v1[0] < $v2[0])
       
$ret = -1;
   
    else   
// Major ver are =
   
{
        if (
$v1[1] > $v2[1])
           
$ret = 1;
        else if (
$v1[1] < $v2[1])
           
$ret = -1;
       
        else 
// Minor ver are =
       
{
            if (
$v1[2] > $v2[2])
               
$ret = 1;
            else if (
$v1[2] < $v2[2])
               
$ret = -1;
            else
               
$ret = 0;
        }
    }
   
    return
$ret;
}
?>
To Top