Three PHP mistakes that will cause you debugging nightmares
January 21, 2009 – 8:18 pm Tags: PHPHere are some PHP mistakes I’ve encountered, which have often been very difficult to track down…
Semicolon after while
Recently in some code I was writing, I had a while loop, which looked something like this:
$i = 0; while($i < 20); { //some code here $i++; }
See that semicolon there? This will cause PHP to silently fall into an infinite loop. You will not get any errors even with E_ALL|E_STRICT error levels – beware of this mistake!
empty() and magic __get method
If you have a class with a __get method, beware of using it with empty():
class Example { public function __get($name) { return 'this should not show up as empty'; } } $e = new Example(); if(empty($e->something)) echo 'This message will show'; $var = $e->something; if(empty($var)) echo 'This message will not show';
The first if will evaluate to true, even though the following if with exactly the same string will not!
Missing semicolon after break or continue
This one can be tricky to track down:
for($i = 0; $i < 10; $i++) { for($j = 0; $j < 10; $j++) { if($i == 0) break print $j; } }
The missing semicolon after the break in the inner loop will cause the code to only output “0″ and then exit. This can be tricky to track down, but there is a good way to avoid this completely: always use braces with control structures
In closing
These three are probably the trickiest I’ve actually seen in code, and for #1 and #2 I must admit I was the person who had written the bad code… in my defense, I must say that #1 should be a parse error from PHP (the braces after the while with no “parent”) and #2 does not make any sense! =)
Do you know any more easy to miss errors in code that can be annoying to find?
ps: welcome dzone users
This post has been getting some nice traffic from dzone. I’d like to welcome any new readers – be sure to subscribe to my RSS feed, as you may find my other posts interesting as well. Some examples of my other recently popular posts are what would make template engines actually useful? and the post on how to implement the Data Access Object pattern in PHP
Also, voting for me on dzone is appreciated – just hit the dz button in the Share this list. Thanks!
Be sure to read the comments below for some more mistakes!

23 Responses to “Three PHP mistakes that will cause you debugging nightmares”
My #1:
$arr = array(‘A’, ‘B’, ‘C’);
foreach ($arr as &$val) {}
foreach ($arr as $val) {}
var_dump($arr);
My #2:
PHP+UTF+BOM
By Sam on Jan 21, 2009
I don’t think #1 should be a parse error – it’s just a code block, which is perfectly parseable. And you could’ve just as well used a for loop anyway
#2 actually does make some sense: the class member itself technically isn’t defined in itself. Instead, calling it returns a value from elsewhere. When that value is then assigned to another variable, that one of course is defined.
That said, they’re still tricky errors to track down
By Vincent on Jan 22, 2009
#1 depends on how you look at it. If you have { } without a control statement, it doesn’t affect anything in any way (afaik) – it’s useless – so why is it allowed?
By Jani Hartikainen on Jan 22, 2009
Good post and great blog! I don’t have any examples as good as those, but one thing actually caused some headache recently. I wanted to know whether an url also contains the scheme (http-prefix) and I used strpos-function. Of course the scheme’s position (if exists) in the string starts from index 0 and I used the !-operator instead of strict comparison with === -operator and yes, you can guess the rest…
true
if (strpos($url, “http”) === false)
// returns false
?>
This is quite obvious and it’s also written in the documentation, but it’s easy to miss
By Olli on Jan 22, 2009
Damn, the php-code doesn’t appear correctly in the previous post. Let’s try without the php-tags.
$url = “http://foobar.com/”;
if (!strpos($url, “http”))
// returns true, because !0 => true
if (strpos($url, “http”) === false)
// returns false
By Olli on Jan 22, 2009
I say: all embrace python’s way of doing it..
By Harro on Jan 22, 2009
Well, parse errors refer to incorrect syntax – a code block is perfectly normal syntax. If you say if((true)) then the inner brackets are useless as well – should that not be allowed?
By Vincent on Jan 22, 2009
To solve your second problem just implement the magic method __isset. (http://www.php.net/__isset) The method __isset() is triggered by calling isset() or empty() on inaccessible members.
By be.coded on Jan 22, 2009
Exactly what be.coded said. Anytime you implement __get, you should be implementing __isset.
something)) {
echo ‘Empty’;
} else {
echo ‘Not empty’;
}
?>
With the code above, you’ll get “Not empty” all the time.
By David Stockton on Jan 23, 2009
That’s a good point, though it’s not obvious that empty would require isset (unless you’ve learned the manual word for word) which is why I listed it.
Also, I wonder if there’s a nice way to enable usage of some html tags in comments for pasting code… it’s not nice that WP screws up your comments.
By Jani Hartikainen on Jan 23, 2009
#1 is absolutely no fault. Looks correct.
If you think PHP should teach you not to do stupid things then better go to school… and try again or look at C++
By resmo on Jan 23, 2009
Well, in fact I would add another one very difficult to detect, related with empty:
empty($v) when $v = “0″;
$v is a string, and you expect empty($v) return false, but empty(“0″) returns true!!
I wrote a post about this a week ago, called
the PHP empty function is wrong, just because of this behavior (which could make sense at some level) but is not what one expects.
By Pau Sanchez on Jan 23, 2009
You can actually wrap miscellaneous parts of your code with curly braces. I’ve seen this done before to organize the code…Maybe some IDE’s use this for collapsing code blocks, who knows? It is legal though.
By kevin on Jan 23, 2009
I learned long ago to implement “is equal to” and “is identical to” comparisons with this syntax:
// is equal too
if (“foo” == $foo) {…}
// is identical to
if (“foo” === $foo) {…}
This helps avoid inadvertently assigning a variable the value of “foo” since:
if (“foo” = $foo)
will raise an error. This tip might be common knowledge but I thought I would mention it.
By nathan on Jan 26, 2009
@Nathan
Yes – it’s a classic. Assignment instead of comparison due misuse of the equals sign.
And cool – your approach with the variable in the letter position will cause an error and’ll not silently change the value if one of the equal signs is missing.
By polarizer on Jan 27, 2009
Also this one never gets old:
try to find out why something isnt comparing…
if($row['something'] != ”){
//do something
}
when the row returns ‘NULL’.
By Oliver Leitner on Jan 29, 2009
I’ve been a victim of the first mistake for a few times. I also make a lot of mistakes from upper case and lower case letters in the code.
By Orlando Orthodontist on Oct 27, 2009