Archive for the ‘Design Patterns’ Category

Lazy Loading in PHP with __autoload

Saturday, April 26th, 2008

__autoload is one of the magic methods added to PHP in version 5. It creates a very easy way for you to manage all your different class files. Actually, with __autoload you don’t need to manage them.

Often you will see in PHP projects files that include the other files needed for that page. You can then end up with a while bunch of require_once calls and so on. This can be quite tedious to maintain and you may not always need all the files.

When you create a new instance of a class PHP checks for it and if it can’t be found the __autoload method is called. It’s passed in one parameter, the name of the class.

  1. function __autoload($class){
  2.  
  3.     require "/path/to/class/files/$class.php";
  4.  
  5. }
  6.  
  7. $x = new Foo();

Above is a simple example of autoload in action. When a new Foo is created the autoload function requires /path/to/class/files/Foo.php. So with a simple naming convention each class in its own file where the file name is the name of the class (similar to Java) you can easily include files.

This example can be taken slightly further to manage hierarchies of classes…

  1. function __autoload($class){
  2.  
  3.     $class = str_replace(‘_’, ‘/’, $class);
  4.     $path = "/path/to/class/files/$class.php";
  5.     require $path;
  6.  
  7. }
  8.  
  9. $x = new Foo_Bar();

The above code simply replaces all underscores ( _ ) with forward slashes ( / ) before requiring the class. The naming convention changes slightly for this, the class name Foo_Bar would be found in following path: /path/to/class/files/Foo/Bar.php.

  1. function __autoload($class){
  2.  
  3.     $class = str_replace(‘_’, ‘/’, $class);
  4.     $path = "/path/to/class/files/$class.php";
  5.  
  6.     if(file_exists($path)){
  7.         require $path;
  8.     } else {
  9.         // Error handling here, log it etc.
  10.         // Exceptions cannot be thrown.
  11.     }
  12.  
  13. }
  14.  
  15. $x = new Foo_Bar_Fail();

The final example shows the same code again with some optional error checking. It allows you to log errors and so on. However, exceptions cannot be thrown by __autoload unless its being called by class_exists. Since this function calls autoload to look for classes. When trying to throw exceptions, PHP runs into a fatal error before its thrown due to the order or __autload. This means a fatal error will be triggered as the class can’t be found and the exception will vanish.

Following up to this post I plan to do one of spl_autoload soon. With this you can have PHP automatically run its own autoload procedure on include paths. For further reading on this follow the link below. The documentation is a little sparse however.

Enjoy, lazy loading!

Useful links;

Design Patterns: Singleton

Saturday, April 19th, 2008

The singleton design pattern is a way of enforcing only one instance of an object. This is achieved by making 3 fairly simple steps to a class. Firstly making the constructor private, creating a static member variable that will contain the instance and then creating a static method for accessing the instance.

So, In PHP it would be;

  1. class Foo {
  2.    
  3.     private static $instance = null;
  4.    
  5.     private function __construct(){
  6.         // Private, so can’t be accessed from outside
  7.     }
  8.    
  9.     private static function getInstance(){
  10.         if($this->instance == null) {
  11.             $this->instance = new Foo();
  12.         }
  13.         return $this->instance;
  14.     }
  15.    
  16.     public function bar(){
  17.         echo "I am one, I am a singleton!";
  18.     }
  19.    
  20. }
  21.  
  22. // Example usage
  23. $foo = Foo::getInstance();
  24. $foo->bar();
  25. // or the chaining method
  26. Foo::getInstance()->bar();
  27. // Note this will not work
  28. $myfoo = new Foo();

Why are singletons good? It’s almost like a global object right? What is good about a singleton as opposed to a concrete class? A concrete class has more flexibility as you can create multiple instances and then each instance can of course be different. However, what if you only ever want one instance of an object and ensure you don’t accidentally make another instance (or another developer doesn’t). You could use globals but they need to be managed somehow and people can still make mistakes and forget things.

The most common example is a database class, you might want to make sure that you only open one connection to the database. Creating multiple instances of database class could (depending how you programmed it) open multiple database connections and be inefficient.

The singleton can also be useful if an object that is used infrequently across a website. It can provide you easy access to it without having to worry about passing the object around. In the above code, you can access that object instance with this snippet of code “Foo::getInstance();”.