If there was an award for the most hated language, the unanimous winner would be PHP. Lots of write-ups criticize it for its nonsensical function naming conventions, inconsistent parameters, sheer absence of what we call, “a well thought design”. However, people on the other side, suggest that writing good code is upto the programmer. Showcasing “Zend Framework”, they assert, PHP is a reasonable language to write clean code with. They say it’s easy to ignore the inconsistencies with a good editor or IDE and adopting best practices. I believed them—until, I encountered something which is completely inexcusable, an ugly case of type juggling.
Type Juggling (or, automatic type casting) is a PHP mechanism which transforms one type to another depending upon the context. As the manual explains, if you add a string to a number, the string will be type casted to a number and not the other way round which results in something like this.
20 + "10Hello World" = 30
Although, I can guess this behavior was added, because string concatenation was already being done with (dot) operator but an ill conceived functionality, as such, can serve a major blow to programmers in trying to figure out why something doesn’t work. Take an example of in_array and type juggling. Suppose, you are checking presence of a string in mixed array. To your surprise, you would find that the following spills out true, because when comparing “Hello” with 0, the former is casted to integer zero.
$arr = array(0, "was", "invented", "in", "india"); var_dump( in_array("Hello", $arr ) );
Although, yes, PHP allows you to do the strict checking, if you invoke the third parameter of in_array but point remains: why should this happen when it is not supposed to?
Let me tell you an incident, how this behavior hit me badly.
bindParam() and Type Juggling
Suppose, you have a big MySQL prepared query for a “school” table which also stores 10th grade scores in column, “10th_grade”. So the query goes like this,
$sql = $pdo->prepare("INSERT INTO school_scores(......10th_grade.....) VALUES(....":10th_grade"....); $sql->bindParam("10th_grade", isset($data["10th_grade"]) ? $data["10th_grade"] : NULL); $sql->execute();
Looks fine? but you get an error: “number of bound variables does not match number of tokens”. You recheck everything, the parameter count on both sides are correct, data is correct but still it is the same. So where is the culprit?
The culprit here is PHP which juggles the type of “10th_grade” to 10 and inserts the assigns value to parameter #10, as bindParam’s first parameter accepts two types of arguments. Finding the flaw here was quite hard because -
a) you don’t know what you are looking for
debugDumpParams doesn’t even print what values were passed making debugging almost impossible.
Although, it can still be said, how such things might still be avoided if you know them but what can’t be answered is – why? Why should one not avoid PHP choose other superior languages over it. The argument of being easy to use and deploy remained true when other stacks lacked simplicity and ease but not today, when web offers far more choices of frameworks and tools. I won’t say I would completely refrain from using PHP but I would definitely avoid it in fear of encountering another of its nastiness.