For most of the thirty-some years that I’ve been paid to program, I’ve worked with assembly language, C, or C++. There have been some diversions to Java, which is pretty painless for a C++ programmer, and always the odd short job or two in anything from Perl to Haskell.

But for the last three months or so I’ve been working full time on a short-timeline project that is using PHP as a general-purpose scripting language. So I’ve been working in this unfamiliar language at a fairly frantic pace, and I have to say that PHP, like Perl, is a strange place for a C programmer.

The Normal Problems

Any tutorial in a scripting language like PHP or Perl always makes a big deal out of Type Juggling, meaning that the type of a variable is inferred from the context in which it is used. In a simple example, a string literal can behave like an integer without any fuss, and vice versa:

{appliance:~} php -r '
> $a = 25;
> printf( strlen($a) . " " );
> printf( 15 + $a );
> printf( "\n" );'
2 40

Maybe it’s just me, but this aspect of PHP doesn’t seem to cause too much trouble. It may be because C and C++ already do implicit data conversions in a lot of situations; PHP just turns the dial up a notch or two.

What does give me a lot of trouble (and this is not exactly news) is that PHP doesn’t require declaration of variables, being perfectly content to create them on first use.

There’s of course nothing wrong with this, but as a C programmer, I have not developed any defensive skills in this area. A PHP programmer is much less likely to enter the following code, because he or she will be a lot more careful about entering variable names:

{appliance:~} php -r '
>$first = "Mark";
>$last = "Nelson";
>$name = $fist . " " . $last;
>print( "$name\n" );'
 Nelson

The good news on variable declaration is that I can jack up PHP’s error reporting so that these mistakes are flagged at runtime. Increased error reporting will also catch another error that plagues C++ programmers:

{appliance:~}php -r '
>$version = "1.2.3";
>print( version . "\n" );'
version

Yes, string literals are just as good without quotes as they are with.

This Week's Puzzle

After a few months I start feeling a bit of a false sense of confidence in my understanding of the language, and naturally, I got some serious comeuppance this week, demonstrated by the following code:

{cslinux1:~} php -r '
>class base {
>  private $secret="42";
>  public function print_secret() { 
>    printf( "$this->secret\n" );
>  }
>};
>class derived extends base {};
>$foo = new derived();
>$foo->secret="43";
>printf( $foo->secret . " " );
>$foo->print_secret();'
43 42

As a C++ programmer, I fully expect the attempt to modify $foo->secret to generate a runtime error. $secret is a private member, and as such I shouldn’t have access to it via the derived class. But the runtime happily makes the assignment.

When I actually print the value, I see that the base class and derived class print different values for $secret. What has happened here is that the assignment actually created a new data member in the derived class with the name $secret.

So what exactly is happening here? The reason for the difference in behavior is that PHP uses the private and protected modifiers to define not just accessiblity, but visibility as well. The $secret member in the base class is not only inaccessible outside of the base class, it is invisible as well.

That invisibility is the key to the behavior. When I try to assign a value to $this->secret, the runtime looks to see if the object of class derived already has a member called $secret. Since the member in the base class is invisible, the conclusion is that there is no member with that name, and as a result, a new variable is created on the fly: derived::$secret.

This can’t be fixed by simply amping up the error level, unfortunately, and it definitely is a problem for C++ or Java programmers. It doesn’t just cause me a lot of confusion, it just seems wrong.

Of course, there is plenty to like about developing in PHP, and it is definitely the right tool for this project. The speed bumps just make the process a lot more interesting. The concept of visibility set me back a few hours, but I’m ready to move on - until I hit the next bit conceptual roadblock.