Categories


Loading feed
Loading feed
Loading feed

PHP Gotchas!


Call them obscure, call them pointless, call them "newb mistakes." Whatever you call them, you've more than likely been tripped up at some point in your PHP coding journey by seemingly odd or illogical behaviors of the language. With PHP being a loosely-typed language, funny things are bound to happen. PHP is an easy language to pick up for the casual coder--things should "just work." But not everyone comes into PHP development with a strong programming background, so here are some charming examples of ways PHP can trip you up if you aren't careful. Put on your thinking caps--here comes the science!

Needles and Haystacks

Say you want to test for the existence of a string inside another string--find the needle in the haystack. It's a pretty common task. Let's let use the strpos() function to knock it out:

if (strpos('abcdefg','abc')){
echo "found it!";
}else{
echo "didn't find it..";
}

Wait a sec! That needle is definitely in that haystack. Why is the strpos() function returning false? Let's peek at the manual entry:

strpos --  Find position of first occurrence of a string

int strpos ( string haystack, mixed needle [, int offset] )

Ah! The strpos() function returns an integer indicating the position (hence the name)! Since our needle is found at the beginning position of the haystack, that function returns 0, which evaluates to false. In addition, the manual states:

If needle is not found, strpos() will return boolean FALSE.

Great, so we'll just patch up the example like so:

if (strpos('abcdefg','abc') != false){
echo "found it!";
}else{
echo "didn't find it..";
}

Huh!? Our 0 return value is not equal to false... or is it? Yes, the integer 0 evaluates to false. We need to check the value as well as the type:

if (strpos('abcdefg','abc') !== false){
echo "found it!";
}else{
echo "didn't find it..";
}

Finally, we get the desired result. The == operator compares value while === (and its inverse !==) compare value as well as type. If you browse the PHP bug tracker, you'll see that this particular gotcha has been submitted many, many times, and marked as a bogus bug report on each occasion.

Cephalopods in my code?

Here's a fun PHP gotcha that I discovered when reading about the Zend PHP Certification:

var_dump(0123 == 123); //outputs bool(false)

This made absolutely no sense to me. Then I discovered that the leading zero made the first integer an octal number, which evaluates to the decimal number 83. Octal notation was included in PHP to make it easy to work with file modes. See the manual page for chmod() for a related gotcha.

While we're at it, don't confuse the first example with:

var_dump("0123" == 123); //outputs bool(true) 

The string "0123" is converted to the integer 123 in the comparison.

Consistent Constants

Pop quiz. What will the following code print?

//MY_UNDEFINED_CONSTANT really is undefined
if (MY_UNDEFINED_CONSTANT){
echo "Kelly Clarkson";
}else{
echo "Kellie Pickler";
}

If you picked Pickler, you'd be wrong in this case. PHP sets an E_NOTICE error here, but if your configuration disregards errors at that level, you should remember undefined constants are treated as the name of the constant, as if you were using the name as a string. And the string "MY_UNDEFINED_CONSTANT" evaluates to true when cast to a boolean.

My Math Teacher Was Lying?

Put a third-grader in a room with computer science major and let them duke this one out:

var_dump(0.7 + 0.1 == 0.8); //outputs bool(false) 

Floating point numbers are definitely not what they seem. Precision becomes a factor with floating point numbers. PHP doesn't seem to do the logical thing when comparing two floats, and this is due to the internal representation of the numbers. The solution is simply never compare floats for equality!

My "Intro to Logic Systems" Professor Was Lying, Too?!

I really started second guessing my student loans when I stumbled across this gotcha:

$x = true and false;
var_dump($x); //outputs bool(true)

Why is 'and' acting like an 'or' operator? Stumped? Maybe this will help:

$y = ($x = true and false);
var_dump($x); //outputs bool(true)
var_dump($y); //outputs bool(false)

This is a case of mistaken operator precedence. In this example, the assignment operator (=) has higher precedence than the 'and' operator, so $x is assigned the value true. The second example clears things up a bit. After the first assignment to $x, the return value (true) is anded with false, yielding false, which is assigned to $y.

__toString() or not to String

PHP version 5 introduced a handy new magic method, __toString(), which lets you do something to the tune of:

class Person {
    private $name;
    
    function __construct($name="John Doe"){
        $this->name = $name;
    }
    
    function __toString(){
        return (string) $this->name;
    }
}

$bob = new Person('Bob');

echo $bob; //prints Bob

That's nice and convenient. But what if I want to add a little punch:

echo $bob . "!"; //prints Object id #1!

What happened to Bob? Turns out the concatenation operation (.) takes precedence, and my __toString() function is never called. What if I cast my object to a string:

$name = (string) $bob;
echo $name . "!"; //prints Object id #1!

Still no dice. The manual tells us that __toString is only called when it is directly combined with echo() or print(). So let's try sending our object, and our emphatic exclamation point as parameters to echo().

echo $bob , "!"; //prints Bob!

Viola! Finally, our __toString() method is called.

Got More Gotchas?

These PHP gotchas are not only informative, but lots of fun to pick apart and share with your programming buddies. If you have any personal horror stories and examples, please share them with in the post comments.

Comments


Friday, April 21, 2006
__TOSTRING IS MY BIGGEST DISAPPOINTMENT
8:04AM PDT · kovrov
Saturday, April 22, 2006
__TOSTRING IN PHP6
7:16AM PDT · bjori
Monday, April 24, 2006
AND THIS THING CONTINUES TO LIVE OUTDOOR IN NATURE ??
8:44PM PDT · Anonymous User [unregistered]
WORKARAUND FLOAT COMPARISON
10:15PM PDT · Onno Marsman [unregistered]
Tuesday, April 25, 2006
FLOAT COMPARISON GOTXCHA: COMPUTER PROGRAMMING 101...
8:37PM PDT · ggiunta
Wednesday, April 26, 2006
FLOATING POINT VALUES
11:28AM PDT · John Herren (staff)
Saturday, May 6, 2006
A COUPLE OTHER ONES
2:08PM PDT · jgarber
Friday, May 12, 2006
STRING COMPARING
1:45AM PDT · camka
Tuesday, May 23, 2006
EREG_REPLACE
7:46AM PDT · Anonymous User [unregistered]
Thursday, June 8, 2006
PHP IT A TRIKY LANGUAGE :-)
5:24PM PDT · alex_vn
Monday, July 3, 2006
OPERATOR PRECEDENCE/LOGIC
10:08PM PDT · Brett Zamir
Sunday, August 6, 2006
FLOATING POINT VALUES
8:54AM PDT · alexturner
Sunday, October 22, 2006
COMPARISON WITH INTEGERS AND STRINGS
4:16PM PDT · dyer85