From Python 2.6 to PHP 5.2: A circuitous journey
November 20th, 2008 byWhen I started heavily using PHP 5.2 (not by choice, I’ll admit), I was impressed, but I suffered from some incorrect assumptions about what PHP5 is and is not capable of doing. The good news is that it is more object oriented than it’s predecessor, but has some caveats to consider. Here are some things to be aware of when switching from a pure OO language to PHP5:
1: A nonexistent PHP array key generates no error or warning. When trying to iterate over a nonexistent array key, a warning occurs. In other languages, both of these conditions throw an exception.
Try this code for example:
<?
$dictionary=array('one'=>'got one','two'=>'have two','four'=>'missing three?');
foreach (array_keys($dictionary) as $key)
{
print "Key is:".$key.", value is:".$dictionary[$key].”\n”;
}
print “Try undefined key three, no warning occurs:”.$dictionary['three'].”\n”;
foreach ($dictionary['three'] as $value)
{
print “Now we’re iterating over a nonexistent key:”;
print “Key is: three, value is:”.$dictionary['three'].”\n”;
}
?>
Running it results in this output:
php test.php Key is:one, value is:got one Key is:two, value is:have two Key is:four, value is:missing three? Try undefined key three, no warning occurs: Warning: Invalid argument supplied for foreach() in /root/test.php on line 8
If it is vital to me to make sure I am aware of missing keys, I only have two choices. If I need a proactive solution, I have to use the array_key_exists() function to do existence checking before use. If I want a reactive solution, I write a log scanner, to pick up on these warnings. In every other OO language I have used, an exception was thrown for this condition, and my exception handling determined if the error was vital enough to have to exit immediately or not. This seems like a more efficient way to handle this condition. I would imaging PHP5 does not do this because of it’s need to be backward compatible with PHP4, but this is a guess.
It would be wonderful to have a -OO flag for PHP, which gives you the option to run PHP and expect more standard, stricter OO behavior in these instances.
2: Warnings cannot be “caught” like exceptions. Exceptions and warnings are distinctly separate beasts, and never the twain shall meet. Fine, I thought, maybe I could detect warnings similar to how we detect errors. But it seems like warnings cannot be detected when they happen. There is no PHP code I know of which can check if a warning had occurred in runtime. I tried to detect it using array error_get_last() but to no avail. if you know how, post your trick here.
3: In PHP, ‘true’ evaluates to an integer ‘1′. To get the boolean ‘true’ value from a ‘true’ statement, one needs to var_export() a true statement. Similarly, or maybe not, ‘false’ evaluates to no output. Here is an example:
<? print "\nThe raw value of a true statement in PHP:".true; print "\nThe raw value of a false statement in PHP:".false; print "\nThe exported value of a true statement in PHP:".var_export(true,true); print "\nThe exported value of a false statement in PHP:".var_export(false,true); print "\n"; ?>
And the output:
The raw value of a true statement in PHP:1 The raw value of a false statement in PHP: The exported value of a true statement in PHP:true The exported value of a false statement in PHP:false
This may not be noticeable to you in a standard expression. But if you’re doing funky stuff, like using the evaluated expression values as key references into the dictionary of a decision tree, for example, 1 does not equal ‘true’, and the difference matters quite a bit.
4: Long running processes with recursive circular references (such as Doctrine code) run out of memory. This is documented in many places, and the free() function works sometimes. A fix is coming in PHP 5.3. The foolproof solution for my code in production today (youch!) is to periodically restart the daemon. If you’re cringing right now, know that you’re not cringing alone.
There may be a part II to this article. Feel free to add your own PHP5 observations.
Gloria


