version_compare

<?php
echo version_compare('anaconda', 'acromantula');
echo
version_compare('baby', 'blister');
echo
version_compare('change', 'cloister');
echo
version_compare('deviant', 'defines');
echo
version_compare('anaconda', 'blister');
echo
version_compare('baby', 'defines');
echo
version_compare('cloister', 'defines');
echo
version_compare('places', 'races');
?>

If you can tell what the output of this is going to be and why then congratulations.

<?php
echo version_compare('anaconda', 'acromantula'); // equals. Maybe first letter comparison?
echo version_compare('baby', 'blister'); // equals. Surely first letter.
echo version_compare('change', 'cloister'); // equals. Really first letter.
echo version_compare('deviant', 'defines'); // defines is lower. That's for the first letter.
echo version_compare('anaconda', 'blister'); // anaconda is lower. Again first letter?
echo version_compare('baby', 'defines'); // defines is lower. HUH?
echo version_compare('cloister', 'defines'); // equals. Really????
echo version_compare('places', 'races'); // races is lower. What's going on...?
?>

The handbook says dev < alpha = a < beta = b < RC < pl, but there is an oddity (bug?) in the implementation which causes version_compare to use these as prefixes. If we add that any string that does not start with any of the strings listed will be equal and below dev (remember, dev prefix!) then suddenly all is understandable (even if it does not make sense). See, eveyrthing beginning with a or b will be alpha or beta but "defines" will be a random string while "deviant" will be equal to "dev"... Same with "places" which is the highest, "pl", but races is a random string which is the lowest.

Edit: I need to answer some of the comments already given. This is not documented anywhere, although I will try to write it up, so RTFM won't help you. The only place to find information about this is the source code of PHP. Second, it might look weird to use version_compare on arbitrary strings but are you sure you want 2.3-gamma1 and 2.3-unstable1 to be equal?

Comments

Seriously?

You're going to use version_compare on non-version type strings? Seriously? WTF...

I'm going to make a PHPWTF about using implode() with an object.

A function should err out on invalid data

I agree that you have no right to consistent output if you feed a function with invalid data. Seeing the examples in the post, which are obviously giving invalid data and expect consistency of the output, I agree with your point, Dave: This isn't a WTF, this is the author getting what he deserves.

On the other hand: Instead of failing silently or producing undefined output, version_compare() should probably just fail in some way - like returning NULL and throwing a warning (which is the traditional PHP way) or throwing an Exception (which is what I would call my preferred solution, but it's not consistent with PHP's ways).

Like earlier versions of PHP's strtotime() which returned 0 in cases where it wasn't able to parse the input data. But 0 is a valid result of the function aswell, so there was no way to discern invalid input from valid beginning-of-the-epoch input. Later this has been fixed and the function returns false now (probably leading people to check with if (!strtotime(...)) and still disallowing beginning of the epoch :-)

Philip

Maybe we're just running out

Maybe we're just running out of WTFs in PHP.

PHP RTFM ?

Maybe PHP WTF should be renamed PHP RTFM ;)

"I hope we've learned something today"

http://xkcd.com/169/

To paraphrase in context: deliberately acting like an idiot and then blaming your tools is not cleverness.

We're testing this for real version strings

You people miss the point. chx and I were testing version_compare() not because we actually expect to be able to compare 'baby' and 'blister'. *sigh*. We're working on #533584: Version dependencies: Support versions with "extra" (alpha, beta, rc, etc) and we need to know how version_compare() is going to behave with version strings like:

7.x-1.0-unstable1
7.x-1.1-alpha3
7.x-2.x
...

Miraculously, it's going to work, but only barely (and only because our CVS configuration on drupal.org prevents much leeway in how people name their versions).

There's still a huge pile of WTF going on here.

For example, it makes sense that "7.1.0-b1" is treated by version_compare() like "7.1.0-beta1". However, WTF is PHP doing where 'b*' is treated as "beta"? What if I happened to call my release "7.1.0-bugfix2"? That's going to equal 7.1.0-beta2? WTF!?

Reasonable to an extent

Thanks Derek, this is a reasonable explanation. However, having a post that says "PHPWTF: Why doesn't version_compare() work like strcmp()?" I guess it's still hard to be a WTF when it's explained clearly in the documentation:

If a part contains special version strings these are handled in the following order: any string not found in this list < dev < alpha = a < beta = b < RC = rc < # < pl = p.

I could create any number of release names. Why doesn't PHP handle delta? awesome-release? super? special? At some point you have to say this is going to make this function impossible and we have to stop at a standard number of releases. If gamma isn't supported but should, is there a PHP issue report for it?

"beta = b" is a lie

I'm not saying it should support arbitrary extra strings at the end of the version string and magically compare the versions properly no matter what someone else envisions as the correct ordering. But "beta = b" is a lie. It's not "b", it's "b*". "bugfix1" == "beta1"? WTF? Why doesn't "bugfix1" get counted as "any string not found in this list"?

Furthermore, why is "b*" == "beta", but only "dev*" == "dev", yet "d*" is an "any string not found in this list"? Again, WTF?

the way it works and the way it should work

Currently there is a hardwired structure of ("extra" strings, weight) pairs in the source code of PHP and it compares as many characters as those "extra" strings have, hence the prefix behaviour. It should be possible to pass in an assocative array to version compare of the version strings your application uses.

did you actually read about this in the manual?

i don't think you did.

"it's documented, so it's not

"it's documented, so it's not a WTF" is a WTF on its own if u ask me

WTF!!!

WTF!!!!!

I used to be more than happy

I used to be more than happy to seek out this internet-site.I wanted to thanks in your time for this glorious read!! I positively enjoying each little bit of it and I have you bookmarked to check out new stuff you weblog post vauxhall for sale / volvo cars

The post is written in very a

The post is written in very a good manner and it entails many useful information for me.airport parking I am happy to find your distinguished way of writing the post.QAA approved Now you make it easy for me to understand and implement the concept.gatwick meet and greet Thank you for the post.The title part of the post made me come here and see what it is about. I love the it and would love to share it with my other friend. Sushi RecipesI wonder if you can put sharing button on it, that will be easy to bring more people to read you. gatwick car parking