PHP Funktion version_compare korrekt verwenden
codestyling | 29. März 2009 | 14:58
Immer wieder findet man Plugins oder Themes, in denen eine eigentümliche Verwendung von version_compare zu finden ist. Wenn man sich jedoch mal genauer die Beschreibung der entsprechenden Funktion in der verfügbaren PHP Dokumentation durchließt, kommt man zu dem Schluss, das ein Vergleich mit > 2.6.999 nur um für 2.7 testen zu wollen, unnötig ist.
Um dies zu demonstrieren, habe ich eine paar Zeilen PHP Code geschrieben, die dieses zeigen.
was steht in der PHP Dokumentation
Die originale Beschreibung der Funktion version_compare ist leider nicht deutsch verfügbar. Deshalb erkläre ich mal kurz, was das Wichtige daran ist. Die Funktionsdefinition sieht so aus:
| PHP | |
1 | mixed version_compare ( string $version1 , string $version2 [, string $operator ] ) |
| timing: 0.046s | |
Es sind also 2 Versionen als Strings nötig, die miteinander verglichen werden. Der 3. Parameter $operator ist optional und gibt den Vergleichsoperator an. Dadurch das dieser Operator optional ist, ist auch das Ergebnis der Funktion nicht direkt definiert, sondern hängt davon ab, ob man einen Operator angegeben hat oder nicht.
ohne den Parameter $operator
Verwendet man die Funktion ohne diesen Operator, ist der Rückgabewert den Funktion ein Zahlenwert der folgende Werte annehmen kann:
- Ergebnis: -1 … die 1. Versionsnummer ist kleiner als die 2. Versionsnummer
- Ergebnis: 0 … die beiden Versionsnummern sind gleich
- Ergebnis: 1 … die 1. Versionsnummer ist größer als die 2. Versionsnummer
mit Verwendung des Parameters $operator
Wenn man einen Vergleichsoperator aus folgender Liste verwendet: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne dann ist das Ergebnis ein Wahrheitswert und kann nur TRUE oder FALSE sein, weil man ja auf einen bestimmten Vergleich testet.
was ist mit Entwicklungsversionen, die Buchstaben enthalten ?
Wer sich schon mal mit Entwicklerversionen beschäftigt hat, wird auf Versionen gestoßen sein, die in etwa so aussehen:
- 2.8-bleeding-edge
- 2.8RC1-123456
Sogar für die korrekten Vergleiche der Entwicklerversionen und Hauptversionen ist in der PHP Funktion gesorgt. Wenn eine Versionskennung also Sonderzeichen wie: ‘_’ oder ‘+’ oder ‘-’ enthält, werden diese intern erst einmal durch ‘.’ ersetzt. Ebenfalls werden Zahlen von Buchstaben mit ‘.’ getrennt, wenn vorhanden. Zu Beispiel wird: ‘4.3.2RC1′ intern zu ‘4.3.2.RC.1′ umgewandelt, bevor der Vergleich ausgeführt wird.
Die Text Anteile in der Versionsnummer werden nach folgenden Schema geordnet und intern im Vergleich benutzt: dev < alpha = a < beta = b < RC < pl. Damit lassen sich dann auch Entwicklungsversionen korrekt einordnen und vergleichen.
Code Beispiel zur Illustration
Ich habe mal ein paar bekannte Versionskennungen von WordPress in ein kleines Script verpackt und die Vergleichsergebnisse als HTML Tabelle ausgeben lassen. Es ist sehr gut zu sehen, wie die Vergleiche arbeiten.
| PHP | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <?php $tests = array( array('2.7.1' => '2.7.1'), array('2.7.1' => '2.7.2'), array('2.7.1' => '2.8-bleeding-edge'), array('2.8' => '2.8-bleeding-edge'), array('2.8alpha' => '2.8-bleeding-edge'), array('2.8-bleeding-edge' => '2.8.1'), array('2.8-bleeding-edge' => '2.7'), array('2.7-bleeding-edge' => '2.8-bleeding-edge'), array('2.8' => '2.8alpha'), array('2.8' => '2.8RC1-123456'), array('2.7' => '2.8alpha'), array('2.7.1' => '2.8alpha'), array('2.7.2' => '2.8alpha'), ); function test_version_compare($first, $second) { $result = '-n.a.-'; if (version_compare($first, $second, '<')) $result = 'ist kleiner'; if (version_compare($first, $second, '>')) $result = 'ist größer als'; if (version_compare($first, $second, '==')) $result = 'ist gleich mit'; return $result; } ?> <table width="100%" style="text-align:center;"> <?php foreach($tests as $test) { foreach($test as $first => $second) { ?> <tr> <td><?php echo $first; ?></td> <td><?php echo test_version_compare($first, $second); ?></td> <td><?php echo $second; ?></td> </tr> <?php } } ?> |
| timing: 0.067s | |
Das Ergebnis des Aufrufes dieser PHP Seite sieht dann so aus:
| 2.7.1 | ist gleich mit | 2.7.1 |
| 2.7.1 | ist kleiner | 2.7.2 |
| 2.7.1 | ist kleiner | 2.8-bleeding-edge |
| 2.8 | ist größer als | 2.8-bleeding-edge |
| 2.8alpha | ist kleiner | 2.8-bleeding-edge |
| 2.8-bleeding-edge | ist kleiner | 2.8.1 |
| 2.8-bleeding-edge | ist größer als | 2.7 |
| 2.7-bleeding-edge | ist kleiner | 2.8-bleeding-edge |
| 2.8 | ist größer als | 2.8alpha |
| 2.8 | ist größer als | 2.8RC1-123456 |
| 2.7 | ist kleiner | 2.8alpha |
| 2.7.1 | ist kleiner | 2.8alpha |
| 2.7.2 | ist kleiner | 2.8alpha |
wie also sollte man die Funktion benutzen
Sehr oft hat man die Anforderung, das ein bestimmter Code-Abschnitt nur bei bestimmten WordPress Versionen ausgeführt werden soll. Sagen wir mal, der Code soll erst ab Version 2.7 ausgeführt werden. In existierenden Plugins findet man nicht selten diesen Test:
| PHP | |
1 | if (version_compare($wp_version, '2.6.999', '>')) ... |
| timing: 0.048s | |
Man kann das zwar so machen, ist aber nicht im Sinne des Erfinders. Die einfachere und auch verständliche Version des Tests kann man so aufschreiben:
| PHP | |
1 | if (version_compare($wp_version, '2.7alpha', '>=')) ... |
| timing: 0.051s | |
Dieser Test schließt alle Entwicklungsversionen von 2.7 mit ein und man sieht auf den ersten Blick, das nur eine gleich oder größere Version hier ein TRUE liefern wird.
Ich denke, diese kleine Übersicht über die Funktionsweise von version_compare räumt mit den falschen Vorstellung zur Arbeitsweise dieser Tests ein wenig auf.






Sergej Müller
29.03.2009 | 15:38Ich glaube, viele Plugin-Entwickler kopieren solche Abfragezeilen einfach irgendwo im Web oder aus einem Plugin heraus ohne nachzudenken, ob es eleganter geht - funktionieren tut es ja. Man vertraut ja der Quelle…
Antworten »