PHP and inconsistent return values

The other day a co-worker asked me why the following snippet of code was acting weird:

1
2
3
4
5
6
7
8
<?php
	$box = 'Tall box';
	if(stripos($box, 'wide ') == 0) {
		echo "It's a wide box!";
	} else {
		echo "It's a tall box!";
	}
?>


C:\> php test.php
It's a wide box!

I’m sure any seasoned PHP devs will spot the error straight away, but it took us a couple of minutes.

From the PHP docs for stripos:

int stripos ( string $haystack , string $needle [, int $offset = 0 ] )
Returns the numeric position of the first occurrence of needle in the haystack string.

Unlike strpos(), stripos() is case-insensitive.

Returns the position as an integer. If needle is not found, stripos() will return boolean FALSE.

This is all well and good, except that in PHP, (0 == false) == true. The PHP interpreter tries to guess the types of both sides of the evaluation, and comes to the conclusion that false is equivalent to 0 (which is in turn equivalent to both NULL and empty string). This is correct in a lot of circumstances, but not great if you are specifically looking for the return value 0.

The solution? In PHP 4 the === operator was introduced (comparison operators). This gets rid of type-juggling (or inference):

===: TRUE if $a is equal to $b, and they are of the same type.

Contrast this simple task to how you might approach it in C#1.

1
2
3
4
5
6
7
8
9
string box = "Tall box";
if (box.IndexOf("wide ") == 0)
{
    Console.WriteLine("It's a wide box!");
}
else
{
    Console.WriteLine("It's a tall box!");
}

The difference here is that String.IndexOf(...) will return -1 if the substring isn’t found.

Working with a statically typed language for a number of years, to me the whole idea of having to deal with a return value which may be this type or that type just feels a bit wrong. One thing worth noting though is that this is not necessarily true in all dynamically typed languages. For instance, Python is a lot more sensible in this scenario.

1
2
3
4
5
6
7
8
>>> None == False
False
>>> 0 == False
True
>>> "test".index("hello")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found

This issue pops up in other PHP library functions (strtok(), current(), readdir() to name a few) maybe due to the standard library’s endemic inconsistencies. There are warnings on the official documentation and the functionality seems to be widely accepted – but I still can’t help feeling that this is counter-intuitive and must be yet another sticking point for new PHP programmers. Python is a great example of a middle ground between PHP and C# – strongly typed but also dynamic. Maybe that’s part of the reason why PHP’s position in the TIOBE is gradually falling while Python’s is rising.


1String.StartsWith() would be better for this specific case.

One thought on “PHP and inconsistent return values

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">