From Python 2.6 to PHP 5.2: A circuitous journey

November 20th, 2008 by comment

When 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

Comments

3 Responses to “From Python 2.6 to PHP 5.2: A circuitous journey”

  1. Jeff says:


    When it throws that warning, it’s because you’re trying to iterate over null, which is what $dictionary['three'] evaluates to. Also, the true/false/1/ stuff is all because of PHPs loose string handling.
    ((string) true) === ’1′
    ((string) false) === ”

    Empty string evaluates to false, and any non-empty string evaluates to true.

    The circular reference collector won’t help you with Doctrine memory bloat. It’s caused by a combination of circular references and the identity map (for canonicalization) contained in every Doctrine Table object. Also, the free() function is dangerous if you still have other references to the object, because they will also be free’d (they’re all references to the same object thanks to the identity map). The best way to avoid the memory problems in long-running processes is to HYDRATE_ARRAY, which makes me sad.

  2. gloriajw says:


    Jeff, thanks for this comment.

    This loose string handling in PHP is quite annoying, because it is not just string handling. It is the default representation returned. You have to eval() these results to get the internal “true” and “false” representation used for, say, a dynamic key in a decision tree, for example.

    PHP makes assumptions that all output is going to a screen. This is really absurd. No other language I’ve worked with does this.

    Re: The doctrine issue, this makes me sad too. So sad, in fact, that I switched the entire project to Python. It now runs, without crashing, and only took a month to rewrite the whole app. Oh well, a lesson learned, I guess.

    Gloria

  3. SeanJA says:


    Ya, the only way to check if something is actually true or false is to check if it is boolean and true/false or to do the === comparison… pain in the arse really: if( is_bool($var) and $var ) or if( is_bool($var) && !$var) or if($var === false) or if ($var === true)

Got something to say?


cheap research papers