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() 返回 -1;如果两者相等,返回 0;第二个版本更低时则返回 1

当使用了可选参数 operator 时,如果关系是操作符所指定的那个,函数将返回 TRUE,否则返回 FALSE

范例

下例使用了 PHP_VERSION 常量,因为它执行的代码包含了 PHP 版本的值。

Example #1 version_compare() examples

<?php
if (version_compare(PHP_VERSION'7.0.0') >= 0) {
    echo 
'I am at least PHP version 7.0.0, my version: ' PHP_VERSION "\n";
}

if (
version_compare(PHP_VERSION'5.3.0') >= 0) {
    echo 
'I am at least PHP version 5.3.0, my version: ' PHP_VERSION "\n";
}

if (
version_compare(PHP_VERSION'5.0.0''>=')) {
    echo 
'I am at least PHP version 5.0.0, my version: ' PHP_VERSION "\n";
}

if (
version_compare(PHP_VERSION'5.0.0''<')) {
    echo 
'I am still PHP 4, my version: ' PHP_VERSION "\n";
}
?>

注释

Note:

PHP_VERSION 常量包含了当前 PHP 的版本。

Note:

注意,类似 5.3.0-dev 的预发行版本,被认为是低于它们的最终发行版本(就像 5.3.0)。

Note:

指定类似 alphabeta 的版本字符串是大小写敏感的。 版本字符串的来源若不遵循 PHP 标准,可能需要在调用 version_compare() 之前先用 strtolower() 转成小写。

参见

User Contributed Notes

ivan maruca 27-Oct-2016 07:16
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
Bob Ray 30-Oct-2015 08:07
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
    */
rlerne at gmail dot com 15-Jan-2015 06:58
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");
?>
mindplay.dk 21-Jul-2012 12:10
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;
}

?>
rogier 30-Nov-2011 05:43
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
loaded67 at hotmail dot com 30-Sep-2009 01:53
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...
insid0r at yahoo dot com 06-Mar-2009 10:05
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;
}
?>
Jonathon dot Reinhart at gmail dot com 30-Oct-2007 04:38
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;
}
?>
opendb at iamvegan dot net 11-Jun-2007 02:01
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', '>')
arnoud at procurios dot nl 29-Sep-2004 11:28
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.
mina86 at tlen dot pl 01-Jul-2004 04:40
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().
eric at themepark dot com 22-Jun-2004 06:50
[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
}
?>
sam at wyvern dot non-spammers-remove dot com dot au 23-May-2004 08:18
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).