[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
}
?>
version_compare
(PHP 4 >= 4.1.0, PHP 5)
version_compare — Vergleicht zwei Versionsnummern im PHP-Stil
Beschreibung
version_compare() vergleicht zwei den PHP-Versionen angeglichenen Versionsnummern. Dies ist beispielsweise nützlich, wenn Code nur unter bestimmten Versionen von PHP funktionieren soll.
Zuerst ersetzt die Funktion _, - und + durch einen Punkt . in den Versionsangaben und setzt vor und nach jeder Kette aus nicht-numerischen Zeichen Punkte ein, sodass beispielsweise '4.3.2RC1' zu '4.3.2.RC.1' wird. Dann wird diese Zeichenkette an den Punkten aufgespalten wie wenn man explode('.', $ver) benutzen würde. Anschließend werden von links nach rechts die Teile verglichen. Wenn ein Teil spezielle Zeichen enthält, werden diese nach der folgenden Reihenfolge behandelt: jede Zeichenkette, die nicht in dieser Liste vorkommt < dev < alpha = a < beta = b < RC = rc < # < pl = p. Auf diese Weise können nicht nur Versionen verschiedener Tiefe wie '4.1' und '4.1.2' sondern auch alle anderen Versionen verglichen werden, die sich auf bestimmte Entwicklungsstadien von PHP beziehen.
Parameter-Liste
-
version1 -
Erste Versionsnummer.
-
version2 -
Zweite Versionsnummer.
-
operator -
Wenn der freiwillige Parameter
operatorangegeben ist, wird auf ein bestimmtes Verhältnis geprüft. Mögliche Operatoren sind: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne.Dieser Parameter berücksicht Groß- und Kleinschreibung, die Werte sollten alle kleingeschrieben werden.
Rückgabewerte
Standardmäßig gibt version_compare() -1 zurück, wenn die erste Version kleiner ist als die zweite, 0, wenn die Versionen gleich sind und 1, wenn die zweite Version kleiner ist.
Wenn der optionale Parameter operator übergeben
wurde, gibt die Funktion TRUE oder FALSE zurück, je nach dem, ob
das mit dem Operator definierte Verhältnis der Wahrheit entspricht
oder nicht.
Beispiele
Das untenstehende Beispiel benutzt die Konstante PHP_VERSION,
die die Version des aktuell ausführenden PHP-Interpreters enthält.
Beispiel #1 version_compare()-Beispiele
<?php
if (version_compare(PHP_VERSION, '6.0.0') >= 0) {
echo 'Ich bin mindestens PHP 6.0.0, und zwar: ' . PHP_VERSION . "\n";
}
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
echo 'Ich bin mindestens PHP 5.3.0, nämlich: ' . PHP_VERSION . "\n";
}
if (version_compare(PHP_VERSION, '5.0.0', '>=')) {
echo 'Ich bin PHP 5. Meine Versionsnummer lautet: ' . PHP_VERSION . "\n";
}
if (version_compare(PHP_VERSION, '5.0.0', '<')) {
echo 'Ich bin PHP 4. Meine Versionsnummer lautet: ' . PHP_VERSION . "\n";
}
?>
Anmerkungen
Hinweis:
Die Konstante
PHP_VERSIONenthält die aktuelle PHP-Version
Hinweis:
Vorveröffentlichte Versionen wie 5.3.0-dev werden als kleiner erkannt als ihre finalen Veröffentlichungen wie 5.3.0.
Siehe auch
- phpversion() - Liefert die aktuelle PHP-Version
- php_uname() - Returns information about the operating system PHP is running on
- function_exists() - Falls die angegebene Funktion definiert ist, wird TRUE zurück gegeben
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...
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', '>')
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;
}
?>
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.
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;
}
?>
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
I know I'm splitting hairs here, but if you're OCD like me
(version_compare(PHP_VERSION, '5.3.0') >= 0)
is about 13% faster than
(version_compare(PHP_VERSION, '5.3.0', '>=')
<?php
$count = 200000;
$start = microtime(true);
for($i=0;$i<$count;$i++) (version_compare(PHP_VERSION, '5.3.0') >= 0);
echo "Real Operator: ".(microtime(true) - $start)."\n";
$start = microtime(true);
for($i=0;$i<$count;$i++) (version_compare(PHP_VERSION, '5.3.0', '>='));
echo "String Operator: ".(microtime(true) - $start)."\n";
?>
<?php
// quick & dirty way to barricade your code during version transitions
assert('version_compare("5", PHP_VERSION, "<"); // requires PHP 5 or higher');
?>
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;
}
?>
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).
Sometimes the code is forward compatible, for example when the code is compatible with all future PHP5 releases.
This function supports .x, for the above example it's : 5.x
<?php
function versionCompare($version1,$version2,$operand) {
$v1Parts=explode('.',$version1);
$version1.=str_repeat('.0',3-count($v1Parts));
$v2Parts=explode('.',$version2);
$version2.=str_repeat('.0',3-count($v2Parts));
$version1=str_replace('.x','.1000',$version1);
$version2=str_replace('.x','.1000',$version2);
return version_compare($version1,$version2,$operand);
}
?>
---
Sina Salek
http://sina.salek.ws/en/contact
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.
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().
