[編輯註記]
在 Matt Mullenweg 的評論後修復的程式碼片段
--jm
[/編輯註記]
因此,簡而言之... 我認為它最好這樣運作
<?php
if (version_compare(phpversion(), "4.3.0", ">=")) {
// 您使用的是 4.3.0 或更新版本
} else {
// 您不是
}
?>
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
version_compare — 比較兩個「PHP 標準化」的版本號字串
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)。
注意:
像是
alpha
和beta
等特殊版本字串區分大小寫。來自任意來源且不符合 PHP 標準的版本字串可能需要在呼叫 version_compare() 之前使用 strtolower() 轉換為小寫。
[編輯註記]
在 Matt Mullenweg 的評論後修復的程式碼片段
--jm
[/編輯註記]
因此,簡而言之... 我認為它最好這樣運作
<?php
if (version_compare(phpversion(), "4.3.0", ">=")) {
// 您使用的是 4.3.0 或更新版本
} else {
// 您不是
}
?>
這個小腳本或許可以幫助您更好地理解版本比較 - 輸出顯示在頂部的註解中。如果需要更多範例,請調整版本列表...
<?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;
}
?>
由於此函數認為 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;
}
?>
請注意,版本號碼上的前導和尾隨空格都可能會破壞 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
*/
有些可能會讓人困惑,但值得一提的是,以下版本比較並不像我預期的那樣工作
version_compare('1.0.1', '1.0pl1', '>')
然而,要讓它運作很容易
version_compare('1.0.1', '1.0.0pl1', '>')
如果您需要處理更複雜的版本號碼,例如 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
*/
實際上,它在任何程度上都有效
<?php
version_compare('1.2.3.4RC7.7', '1.2.3.4RC7.8')
version_compare('8.2.50.4', '8.2.52.6')
?>
兩者都會得到 -1(即左邊低於右邊)。
如果你夠仔細,這個函式其實在比較非 PHP 本身的程式版本號時相當好用。我曾經用它來比較 MySQL 的版本號。唯一的問題是,`version_compare` 不會將 MySQL 使用的 'gamma' 看作比 'alpha' 或 'beta' 還要新,因為後兩者會被特殊處理。不過,只要你記住這一點,應該就不會有任何問題。