There may be a faster way to do some of this, but I needed to take into account gamma and service pack releases. I had no need for the comparison operator functionality, so that does not exist in this version.
<?php
function versionCompare($v1, $v2) {
//reformat v1
$v1 = str_replace(array('_','-','+'),'.',strtolower($v1));
$v1 = str_replace(array('alpha','beta','gamma'), array('a','b','g'), $v1);
$v1 = preg_split("/([a-z]+)/i",$v1,-1, PREG_SPLIT_DELIM_CAPTURE);
array_walk($v1, create_function('&$v', '$v = trim($v,". ");'));
$v1 = explode('.',trim(implode('.',$v1),'. '));
//reformat v2
$v2 = str_replace(array('_','-','+'),'.',strtolower($v2));
$v2 = str_replace(array('alpha','beta','gamma'), array('a','b','g'), $v2);
$v2 = preg_split("/([a-z]+)/i",$v2,-1, PREG_SPLIT_DELIM_CAPTURE);
array_walk($v2, create_function('&$v', '$v = trim($v,". ");'));
$v2 = explode('.',trim(implode('.',$v2),'. '));
//start comparison by padding sizes
if (count($v1) < count($v2)) { $v1 = array_pad($v1, count($v2), '0'); }
elseif (count($v1) > count($v2)) { $v2 = array_pad($v2, count($v1), '0'); }
//order chart
$chart = array('dev','a','b','g','rc','pl','0','sp');
foreach ($v1 as $n => $v) {
//check if equal
if ($v === $v2[$n]) { continue; }
//check if both numbers
if (preg_match("/^[0-9]+$/",$v) && preg_match("/^[0-9]+$/",$v2[$n])) {
if ($v < $v2[$n]) { return -1; }
if ($v > $v2[$n]) { return 1; }
}
//check if one number (not 0)
if (preg_match("/^[0-9]+$/",$v) && $v != '0') { return 1; }
if (preg_match("/^[0-9]+$/",$v2[$n]) && $v2[$n] != '0') { return -1; }
//account for both being symbols (and/or zeros)
if (array_search($v, $chart) < array_search($v2[$n], $chart)) { return -1; }
if (array_search($v, $chart) > array_search($v2[$n], $chart)) { return 1; }
return false;
}
return 0; //return 0 if equal
}
//using old function returns -1, as SP is not recognized.
var_dump(version_compare("2.2.RC.2SP1","2.2.RC.2"));
//using new function returns 1, as you'd expect.
var_dump(versionCompare("2.2.RC.2SP1","2.2.RC.2"));
?>
version_compare
(PHP 4 >= 4.0.7, PHP 5)
version_compare — ふたつの "PHP 標準" バージョン番号文字列を比較する
説明
version_compare()は、ふたつの "PHP 標準" バージョン 番号文字列を比較します。この関数は、いくつかのバージョンの PHP でのみ 動作するプログラムを書きたい場合に有用です。
この関数はまず、バージョン文字列の _, -, + をドット . で置き換えます。 さらに、数値でない部分の前後にドット . を追加します。 例えば '4.3.2RC1' は '4.3.2.RC.1' となります。 次に、explode('.', $ver) とするのと同じように結果を分割し、左から右へ 各部分を比較していきます。特殊な文字列が含まれている場合は以下の順で 並べ替えます: dev < alpha = a < beta = b < RC < pl. この方法により、'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, '6.0.0') === 1) {
echo '6.0.0 より新しいバージョンの PHP を使っています。バージョンは ' . PHP_VERSION . " です。\n";
}
if (version_compare(PHP_VERSION, '5.3.0') === 1) {
echo '5.3.0 より新しいバージョンの PHP を使っています。バージョンは ' . PHP_VERSION . " です。\n";
}
if (version_compare(PHP_VERSION, '5.0.0', '>')) {
echo 'PHP 5 を使っています。バージョンは ' . 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) より小さいとみなされます。
version_compare
01-Dec-2008 02:35
08-Mar-2008 03:54
<?php
// quick & dirty way to barricade your code during version transitions
assert('version_compare("5", PHP_VERSION, "<"); // requires PHP 5 or higher');
?>
31-Oct-2007 06:18
It should be noted that version_compare() considers 1 < 1.0 < 1.0.0 etc. I'm guessing this is due to the left-to-right nature of the algorithm.
31-Oct-2007 12: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;
}
?>
11-Jun-2007 09: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', '>')
29-Sep-2004 06: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.
01-Jul-2004 11: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().
22-Jun-2004 01: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
}
?>
24-May-2004 03: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).