2012.09.30

PHP is not easy as it may seem

PHP is often regarded to as an easy web programming language/environment with a fast learning curve. Perhaps, this is mainly due to the following reasons.

  1. You can do something useful very soon: once you understand how to get variables from outside (GET and POST), deal with associative arrays and connect to a DB, you [think you] are almost done, and can understand roughly 90% of the PHP code around.
  2. It’s easy to find code snippets that do what you need. If I google “php read xml” the first result I get is a very easy tutorial written in my own language that needs about five minutes to get basic things done.
  3. If you can’t find a copy&paste snippet with Google, a huge community of PHP developers can drop you the 3-4 lines of code you need. Just say “Thanks!”.
  4. PHP can boast a large number of (widely available) extensions that do quite everything: database connection, XML parsing, image processing, and much more... at your fingertips.
    On the other hand, a web container like Tomcat just runs servlets and JSPs: that’s pretty basic. You have to grab the Java libraries your application needs and ship them with your WAR.
  5. Ubiquity: a lot of free and low-cost decent PHP hosting providers are available in the market.

The only apparent straightforwardness of PHP — compared to the complexity of its main competitor, Java EE — pushed many beginner web developers onto it. Java EE, in fact, seems complicated and unnecessarily cumbersome: in order to accomplish a relatively simple task (for example, a contact e-mail form), you have to learn Java (and therefore OOP concepts) at a good level, and even if you can use JSPs — which are quite similar to PHP scripts — you soon understand that they are just a small spot in a bigger picture, along with servlets, tag libraries, and so on...

Personally, I would use Java EE even for small web projects, because once you know how to deal with it, everything get easier and easier — and it scales better. But I understand the attractiveness of PHP is the one of making it possible, even for a beginner web developer, to write a contact e-mail form in a couple of minutes — no matter if the code is a monolithic 1000-lines index.php crap that has to be rewritten from scratch when it comes to change anything! :)

To get to the point, I don’t think PHP is easy at all. The there are many caveats, and I’ll try to give you some example here.

  1. Killer flags.

    Many PHP web applications just stop working if the server administrator writes this single line in the php.ini file: short_open_tag = off. This is uncute and looks terribly fragile. If a PHP script assumes short_open_tag is On and for some reason this flag unexpectedly goes Off, then some PHP block could be skipped and considered as text: not only the web application no longer works, but might reveal sensitive information attackers can exploit.

    Are your PHP applications short_open_tag-robust? Mines are not, because short_open_tag makes a lot of sense to me and I don’t want to miss the opportunity to use it.

    The rationale is: PHP configuration flags are not innocent, are not safe to switch, are not always easy to understand. Even a small change can expose your web application to severe issues.

  2. Killer empty lines.

    If you leave an empty line after the last closing ?> tag in an included script and then you call header after including that script, you will get the infamous headers have already been sent warning, and the first time it happens, it will take a couple of hours for you to understand why. (Hint: just omit the last closing tag everywhere.)

  3. Duck typing.

    PHP variables have a type, but you have little control over it. PHP decides for you determining the type of the variable “by the context in which the variable is used” (source). That’s fantastic, no more boring variable types, isn’t it?

    Not really. What happens, let’s say, if you mistakely concatenate a string to an integer using the + operator instead of the . operator?

    $num = 5;
    echo 'The value of num is: '+$num;
    

    The string is converted into an integer (often zero) and summed to the integer you were trying to concatenate: the result (an integer) is printed (in the example above, 5). No errors and no clue of what the problem could be.

    Moreover, let’s look at the following code:

    if (strpos('foo', 'x') == 0) { // does 'foo' start with 'x'?
        echo 'Found it!';
    }
    

    Apparently, it looks like the body of the if will not be executed, because 'foo' does not start with 'x'. But you have to carefully read the documentation of the strpos function to see that there is a terrible bug in this code. The strpos function returns an integer representing the position of the first occurrence of a substring in a string... or boolean FALSE if the substring is not found! Because of duck typing, FALSE == 0. You have to use the === (identical) operator to match also the type of the variable.

    Languages with strong typing (like Java) can point these mistakes to us before executing the code.

  4. Common pitfalls causing meaningless error messages.

    PHP 5 introduced type hinting. This means you can force the parameters of the functions to be arrays or object of a certain class.

    Well, if you try to run this code:

    function foo(string $bar) {
        echo $bar;
    }
    
    foo('bar');
    

    This is the error message you get: Argument 1 passed to foo() must be an instance of string, string given, called in ...
    Actually, you can’t type-hint string, but I bet everybody tried at least once and was given this meaningless error message.

  5. No robust backward compatibility.

    An example? PHP 5 supports passing parameters to functions by reference, and that’s good. But as of PHP 5.3.0, you shouldn’t pass by reference in the function call, but only in the function signature. If you don’t obey this rule, you just get a “deprecated warning”, and everything works just fine. But, as of PHP 5.4.0, you get a fatal error!

    If your php.ini settings silence “deprecated warnings” then you just don’t know if PHP developers are changing their (creative) minds — thus breaking your application. Do you periodically check you aren’t using deprecated features in your PHP scripts?
    It’s good to remember that Tomcat 7 can run legacy Servlet 2.2 applications with none of these annoying issues.

That’s what it comes up to my mind, but there’s probably more. Please share your thoughts by leaving a comment.

Tags: php
comments powered by Disqus
Fork me on GitHub