« Back to blog

Using Traits in PHP 5.4

One interesting new feature of PHP 5.4 is traits.  Traits add horizontal inheritance to the single inheritance language.  Simas Toleikis does a good job of explaining what traits are and how they work in one of his blog posts.  Although traits may be a controversial addition that walks the line of multiple inheritance, I wanted to find a good use for them as I'm sure new frameworks like Lithium will once they provide support for PHP 5.4.

One of my goals for my personal PHP library is to have a good core Object class that can be extended by every other class within my applications.  This class needs to be flexible in order to support the many design patterns that my applications may require.  Here's a simple example of how I started using traits...

First, I created an Object class with a protected constructor.  So, instead of instantiating the class using $obj = new Object(), you do $obj = Object::getInstance();

class Object {
  
  protected function __construct() {
    
  }

  public static function getInstance() {
    $className = get_called_class();
    return new $className();
  }

}

Adding the following two traits will allow subclasses of Object to act as singletons or force static access without writing tons of code:

trait Singleton {

  protected static $_instance;

  public static function getInstance() {
    if(!isset(static::$_instance)) {
      $className = get_called_class();
      static::$_instance = new $className();
    }
    return static::$_instance;
 }

}

trait StaticAccess {
   public static function getInstance() {
      throw new Exception("Instances of this class are not allowed!");
   }
}

Now, subclasses of the Object class can employ the singleton pattern or enforce static-only access with a single line of code in each subclass:

class MySingleton extends Object {
  use Singleton;
}
$x = MySingleton::getInstance();
$x->name = "Pat";

$y = MySingleton::getInstance();
assert("$x->name == $y->name"); // passes

class MyStatic extends Object {
  use StaticAccess;
}

$obj = MyStatic::getInstance(); // throws Exception

If you get a segmentation fault when testing this, you might need to download the latest build of PHP 5.4. You can find it here.