2024年PHP日本大会

version_compare

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

version_compare比较两个“PHP 标准化”的版本号字符串

描述

version_compare(string $version1, string $version2, ?string $operator = null): int|bool

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

可选运算符。可能的运算符包括:<lt<=le>gt>=ge===eq!=<>ne

此参数区分大小写,值应为小写。

返回值

默认情况下,version_compare() 如果第一个版本低于第二个版本,则返回 -1;如果它们相等,则返回 0;如果第二个版本低于第一个版本,则返回 1

当使用可选的 operator 参数时,如果关系与运算符指定的相同,则该函数将返回 true,否则返回 false

示例

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

示例 #1 version_compare() 示例

<?php
if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
echo
'我的PHP版本至少是7.0.0,我的版本:' . PHP_VERSION . "\n";
}

if (
version_compare(PHP_VERSION, '5.3.0') >= 0) {
echo
'我的PHP版本至少是5.3.0,我的版本:' . PHP_VERSION . "\n";
}

if (
version_compare(PHP_VERSION, '5.0.0', '>=')) {
echo
'我的PHP版本至少是5.0.0,我的版本:' . 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 标准的版本字符串可能需要在调用 version_compare() 之前使用 strtolower() 转为小写。

参见

添加注释

用户贡献的注释 9 个注释

eric at themepark dot com
20 年前
[编辑注]
在 Matt Mullenweg 的评论后修复了代码片段

--jm
[/编辑注]

简而言之……我相信它最好这样工作

<?php
if (version_compare(phpversion(), "4.3.0", ">=")) {
// 您使用的是 4.3.0 或更高版本
} else {
// 您不是
}
?>
mindplay.dk
12年前
这个小脚本或许可以帮助你更好地理解版本比较 - 输出显示在顶部的注释中。如果需要更多示例,请调整版本列表……

<?php

# 1 < 1.0
# 1.0 < 1.01
# 1.01 = 1.1
# 1.1 < 1.10
# 1.10 > 1.10b
# 1.10b < 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;
}

?>
[email protected]
15年前
由于此函数认为 1 < 1.0 < 1.0.0,其他人可能会发现此函数有用(它认为 1 == 1.0)

<?php
//比较两组版本,其中主版本/次版本/等发行版由点分隔。
//如果两者相等则返回 0,如果 A > B 则返回 1,如果 B < A 则返回 -1。
function version_compare2($a, $b)
{
$a = explode(".", rtrim($a, ".0")); //将版本拆分为多个部分并删除尾随的 .0
$b = explode(".", rtrim($b, ".0")); //将版本拆分为多个部分并删除尾随的 .0
foreach ($a as $depth => $aVal)
{
//迭代 A 的每个部分
if (isset($b[$depth]))
{
//如果 B 与 A 到此深度匹配,则比较值
if ($aVal > $b[$depth]) return 1; //返回 A > B
else if ($aVal < $b[$depth]) return -1; //返回 B > A
//此时相等的结果是不确定的
}
else
{
//如果 B 到此深度与 A 不匹配,则 A 在排序顺序中位于 B 之后
return 1; //所以返回 A > B
}
}
//此时,我们知道 A 和 B 扩展到的深度是等效的。
//循环结束是因为 A 短于 B,或者两者相等。
return (count($a) < count($b)) ? -1 : 0;
}
?>
Bob Ray
9年前
请注意,版本号上的前导和尾随空格都可能破坏 version_compare()。

在 PHP 5.6.8 上测试
<?php
echo "\n应该为 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\n应该为 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\n应该为 -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');

/* 输出
应该为 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

应该为 1
'1.1.1-pl' vs. '1.0.0-pl' ---> 1
' 1.1.1-pl' vs. '1.0.0-pl' ---> -1

应该为 -1
'1.0.0-pl' vs. '1.1.1-pl' ---> -1
'1.0.0-pl' vs. ' 1.1.1-pl' ---> 1
*/
rogier
13年前
请注意,如果提供未列出的运算符(例如 ===),此函数将返回 NULL 而不是 false。

在 PHP 5.3.0,Win32 上测试
[email protected]
17年前
可能让一些人感到困惑,但值得一提的是,以下版本比较的结果并非完全符合我的预期
version_compare('1.0.1', '1.0pl1', '>')

但是,很容易使其正常工作
version_compare('1.0.1', '1.0.0pl1', '>')
Lcuis
2年前
如果您需要处理更复杂的版本号,例如 alpha、beta……,这里有一些可以帮助您的代码

function multiExplode($delimiters,$string){
$pattern = '/['.preg_quote($delimiters).']/';
return(preg_split( $pattern, $string ));
}

function isInteger($input){
return(ctype_digit(strval($input)));
}

function keepIntsStartArray($arr){
$nonIntMappings=[
"alpha"=>1,
"beta"=>2,
"gamma"=>3,
"delta"=>4,
"epsilon"=>5,
"zeta"=>6,
"eta"=>7,
"theta"=>8,
"iota"=>9,
"kappa"=>10,
"lambda"=>11,
"mu"=>12,
"nu"=>13,
"xi"=>14,
"omicron"=>15,
"pi"=>16,
"rho"=>17,
"sigma"=>18,
"tau"=>19,
"upsilon"=>20,
"phi"=>21,
"chi"=>22,
"psi"=>23,
"omega"=>24,
];
$ret=[];
foreach($arr as $i){
if(!isInteger($i)){
if(!array_key_exists($i,$nonIntMappings)){
break;
}
$ret[]=$nonIntMappings[$i];
}
$ret[]=$i;
}
return($ret);
}

function appVersionBigger($v1,$v2,$orEqual=false){
$delimiters=".-+";
$a1=keepIntsStartArray(multiExplode($delimiters,$v1));
$a2=keepIntsStartArray(multiExplode($delimiters,$v2));
$len=count($a1);
if($len>count($a2)){
$len=count($a2);
}
for($i=0;$i<$len;$i++){
$n1=$a1[$i];
$n2=$a2[$i];
if($n1>$n2){
return(true);
}
if($n1<$n2){
return(false);
}
}
if(count($a1)>count($a2)){
return(true);
}
if(count($a1)<count($a2)){
return(false);
}
return($orEqual);
}

// 使用示例

$versions=[
"1.2.3-45"=>"1.2.3-45",
"1.2.3-44"=>"1.2.3-45",
"1.2.3-46"=>"1.2.3-45",
"1.2.3"=>"1.2.3-45",
"1.2.4"=>"1.2.3-45",
"1.2.2"=>"1.2.3-45",
"1.2"=>"1.2.3-45",
"1.3"=>"1.2.3-45",
"1.2.3-ios"=>"1.2.3-and",
"1.2-ios"=>"1.2.3-and",
"2-ios"=>"1.2.3-and",
"1.2.3-alpha"=>"1.2.3-beta",
"1.2.3-beta"=>"1.2.3-alpha",
"1-gamma"=>"1.2.3-beta",
"1-alpha"=>"1.2.3-beta",
];

foreach($versions as $v1=>$v2){
echo("v1: ".$v1."\tv2: ".$v2."\tgt: ".(appVersionBigger($v1,$v2,false)?"true":"false")."\tge: ".(appVersionBigger($v1,$v2,true)?"true":"false")."\n");
}

// 使用PHP 8.1.8版本的输出
/*
v1: 1.2.3-45 v2: 1.2.3-45 gt: false ge: true
v1: 1.2.3-44 v2: 1.2.3-45 gt: false ge: false
v1: 1.2.3-46 v2: 1.2.3-45 gt: true ge: true
v1: 1.2.3 v2: 1.2.3-45 gt: false ge: false
v1: 1.2.4 v2: 1.2.3-45 gt: true ge: true
v1: 1.2.2 v2: 1.2.3-45 gt: false ge: false
v1: 1.2 v2: 1.2.3-45 gt: false ge: false
v1: 1.3 v2: 1.2.3-45 gt: true ge: true
v1: 1.2.3-ios v2: 1.2.3-and gt: false ge: true
v1: 1.2-ios v2: 1.2.3-and gt: false ge: false
v1: 2-ios v2: 1.2.3-and gt: true ge: true
v1: 1.2.3-alpha v2: 1.2.3-beta gt: false ge: false
v1: 1.2.3-beta v2: 1.2.3-alpha gt: true ge: true
v1: 1-gamma v2: 1.2.3-beta gt: true ge: true
v1: 1-alpha v2: 1.2.3-beta gt: false ge: false
*/
sam at wyvern dot non-spammers-remove dot com dot au
20 年前
实际上,它适用于任何程度

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

两者都将返回 -1(即左侧小于右侧)。
arnoud at procurios dot nl
20 年前
如果您小心谨慎,此函数实际上非常适合比较来自PHP自身以外程序的版本号。我已经用它来比较MySQL版本号。唯一的问题是,version_compare不识别mysql使用的“gamma”附加版本比“alpha”或“beta”晚,因为后者两者被特殊处理。但是,如果您记住这一点,就不会有任何问题。
To Top