Fun with PHP 5.3

02 September, 2009

Version 5.3 has been out a little over two months, so it's nigh time I dug into into it! It's surprising that I've waited this long to get around to installing it, as it contains some tidbits that I have been eagerly awaiting since talk about PHP 6 began a couple years ago. In addition to the usual bug fixes, this version includes support for two features of particular interest to me: namespaces and variable static method calls.

Variable Static Method Calls

One of the biggest annoyances prior to 5.3, was that one couldn't call the static method of a class using a variable. The following code, for example, just plain would not work:

toggle plain-text
  1. <?php
  2.  
  3. $variable::static_method();

It is a very small change, but it makes all the difference in the world when using factories, builders, and singletons. Consider the following animal classes:

toggle plain-text
  1. <?php
  2.  
  3. class Cow
  4. {
  5.     public static $name = 'Herbert';
  6.    
  7.     public static function speak()
  8.     {
  9.         print 'moo';
  10.     }
  11. }
  12.  
  13. class Pig
  14. {
  15.     public static $name = 'Leon';
  16.    
  17.     public static function speak()
  18.     {
  19.         print 'oink';
  20.     }  
  21. }
  22.  
  23. class Cat
  24. {
  25.     public static $name = 'Oedipus';
  26.    
  27.     public static function speak()
  28.     {
  29.         print 'Meow';
  30.     }
  31. }
  32.  
  33. //animals!
  34. $animals = array('Cow', 'Pig', 'Cat');
  35.  
  36. //show variable static function calls
  37. foreach ($animals as $animal)
  38. {
  39.     //make silly sounds
  40.     print $animal::$name . ':';
  41.     $animal::speak();
  42.     print "\n";
  43. };

If you have ever used the singleton pattern, you know that the key to fetching object instances is to call the instance() or similarly named function statically. Prior to 5.3, it was impossible to dynamically call upon singletons without using trickery, such as the call_user_func or call_user_func_array methods. Now, it is very easy to simply use the syntax demonstrated above.

Another situation where the dynamic call proves useful is when trying to fetch the constants of a particular class. In the past, the developer was forced to instantiate the class, and then use a custom function to fetch the constant and return it, or worse yet, use Reflection methods to try and parse the constants from the class. As of 5.3, it's very easy to do the following:

toggle plain-text
  1. <?php
  2.  
  3. class Cow
  4. {
  5.     const NAME = 'Herbert';
  6. }
  7.  
  8. $cow = 'Cow';
  9. print $cow::NAME;

Namespaces

PHP has long needed support for namespaces, and even though the new implementation is a little weird, it is certainly better than nothing (for most of us). At first, I was a little put-off by the Backslash delimiter (\) used for namespaces, as it is a departure form the C-like syntax that PHP usually honors. After a few uses, however, I found the PHP implementation quite easy to use, and could really care less whether it irks the C zealots who already hate PHP for a million other reasons besides this one.

The following code sample contains some different examples to try out:

toggle plain-text
  1. <?php
  2.  
  3. namespace Work;
  4.  
  5. class Computer
  6. {
  7.     public static function power()
  8.     {
  9.         print "Boo. I don't want to work now.\n";
  10.     }
  11. }
  12.  
  13. namespace Play;
  14. class Computer
  15. {
  16.     public static function power()
  17.     {
  18.         print "All right! Video games!\n";
  19.     }
  20. }
  21.  
  22. //using sub namespace
  23. namespace Work\Exciting;
  24. class Computer
  25. {
  26.     public static function power()
  27.     {
  28.         print "This Job Rocks!\n";
  29.     }
  30. }
  31.  
  32. //Sample Usage Method #1
  33. namespace Work;
  34. Computer::power();
  35.  
  36. namespace Play;
  37. Computer::power();
  38.  
  39. namespace Work\Exciting;
  40. Computer::power();
  41.  
  42. //Sample Usage Method #2
  43. \Work\Computer::power();
  44.  
  45. \Play\Computer::power();
  46.  
  47. \Work\Exciting\Computer::power();

In a real-world implementation, I would caution against placing multiple namespaces in the same file, but if you absolutely had to, you could use the bracket method to declare your namespaces in addition to methods outlined above. This only works if you place your namespaces in a separate file, with no additional code among them. Consider the following:

toggle plain-text
  1. <?php
  2.  
  3. //another way to declare namespaces when using multiple namespaces in a file
  4. namespace BracketSyntax
  5. {
  6.     class Computer
  7.     {
  8.         public static function power()
  9.         {
  10.             print "I am in a different file!\n";
  11.         }
  12.     }
  13. }
  14.  
  15. namespace BracketSyntax2
  16. {
  17.     class Computer
  18.     {
  19.         public static function power()
  20.         {
  21.             print "I am in a different file too!\n";
  22.         }
  23.     }
  24. }

If you placed the above code in a file named bracketed_ns.php, you could call the appropriate classes in the same fashion as the previous examples:

toggle plain-text
  1. <?php
  2.  
  3. //Method #3
  4. require('bracketed_ns.php');
  5. \BracketSyntax\Computer::power();
  6. \BracketSyntax2\Computer::power();

If you are interested in checking out additional changes in version 5.3, head on over to the php.net release announcement page for a full list of new features.

};