Article

PHP5: Coming Soon to a Webserver Near You

Page: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Next

A Little Decoration

Overloading might also be used to implement a Decorator pattern (a Decorator pattern provides an alternative to subclassing). For example:

       
<?php        
class FileList {        
   var $listing;        
   function __construct($path) {        
   $this->listing = array();        
   $path = realpath($path);        
   $dir = Dir($path);        
   while (false !== ($entry = $dir->read())) {        
     if ( is_file($path.'/'.$entry) ) {        
       $file = array();        
       $file['name'] = $entry;        
       $file['size'] = filesize($path.'/'.$entry);        
       $file['ctime'] = filectime($path.'/'.$entry);        
       $file['atime'] = fileatime($path.'/'.$entry);        
       $this->listing[]=$file;        
     }        
   }        
   }        
 function fetch() {        
   $file = each ( $this->listing );        
   if ( $file ) {        
     return $file['value'];        
   } else {        
     reset ( $this->listing );        
     return false;        
   }        
 }        
 function getFileByName($name) {        
   foreach ( $this->listing as $file ) {        
     if ( $file['name'] == $name ) {        
       return $file;        
     }        
   }        
   return false;        
 }        
}        
       
class FileSortDecorator {        
 var $fileList;        
 function __construct($fileList,$sortBy='name') {        
   $this->fileList = $fileList;        
   $sort = array();        
   foreach ( $this->fileList->listing as $file ) {        
     $sort[]=$file[$sortBy];        
   }        
   array_multisort($sort,$this->fileList->listing);        
 }        
 function __call($method,$params) {        
   return call_user_func_array(        
           array($this->fileList,$method),$params);        
 }        
}        
       
$fileList = new FileList('./');        
$sortDecorator = new FileSortDecorator($fileList,'size');        
       
echo ('<b>fetch:</b>');        
while ( $file = $sortDecorator->fetch() ) {        
 echo ('<pre>');        
 print_r($file);        
 echo ('</pre>');        
}        
       
echo ('<b>getFileByName:</b><pre>');        
print_r($sortDecorator->getFileByName('overload.php'));        
echo ('</pre>');        
?>        

Script: overload_decorator.php

The FileSortDecorator class decorates the FileList class by sorting the list of files by a particular array key. At the same time, it allows the FileList methods to be called through it, using the __call() method.

Warning: overloading is very powerful but will constitute a "hack" in most circumstances. How can you perform introspection on an overloaded class, for example? Marcus Baker, author of the excellent Simple Test Framework for PHP Unit Testing, raised some very valid concerns about PHP's overloading here.

Aside from integration with other platforms and hacking, overloading provides some interesting opportunities for PHP developers to apply the Aspect Oriented Paradigm (as Markus mentions in his post), and to implement something like Python's Metaclasses.

Note: PHP does not support operator overloading (so no $myObject++).

Static, Final and Constant

PHP5 provides three more important keywords; static, final and constant.

Static

The static keyword can be declared against class variables or methods, to allow them to be accessed externally without instantiating the class itself. With PHP4 this was already possible for class methods, using the :: operator, but the important step forward is it can now be applied to class variables.

Here's a static class member variable:

       
<?php        
class MyStatic {        
   static $foo;        
   var $bar;        
}        
       
MyStatic::$foo = 'Red';        
       
# Fatal error: Access to undeclared static property: mystatic::$bar        
// MyStatic::$bar = 'Blue';        
       
echo ( MyStatic::$foo );        
?>        

Script: static_var.php

Where class methods are concerned, the static keyword is less important, as methods can be called statically anyway (otherwise PHP5 would break a lot of backward compatibility with PHP4):

       
<?php        
class MyStatic {        
   static function Foo() {        
       return 'This is foo()';        
   }        
   function Bar() {        
       return 'This is bar()';        
   }        
}        
       
echo ( MyStatic::foo().'<br />' );        
echo ( MyStatic::bar().'<br />' );        
       
$obj = new MyStatic();        
       
# Fatal error - cannot call static method via object instance        
// echo ( $obj->foo().'<br />' );        
echo ( $obj->bar().'<br />' );        
?>        

Script: static_method.php

Essentially, all methods can be called statically in PHP5 anyway, as was possible in PHP4. However, the static keyword prevents a method declared with it from being called via an object instance, as the example demonstrates.

If you liked this article, share the love:
Print-Friendly Version Suggest an Article

Sponsored Links