PHP 5 Static class variable inheritence

PHP 5 doesn’t seem to attempt to implement any kind of inheritance for properties within static classes. This can be mean having to duplicate code within static subclasses. As an example, we would like to have a parent class (this is using the Singleton pattern) such as this:

abstract class DataTable
{
 protected static $instance;

 protected function __construct()
 {
  parent::__construct();
 }

 public static function getInstance()
 {
  if(!isset(self::$instance))
  {
   self::$instance = new self();
  }
  return self::$instance;
 }
}

And then to create a subclass to inherit from it:

class PageTable extends DataTable
{
}

And then creating an instance of PageTable could be done by running a line of php such as this:

$pageTable = PageTable::getInstance();

Which would then return an instance of PageTable.

Then we might want another subclass such as:

class ContentTable extends DataTable
{
}

And so be able to create an instance of ContentTable with:

$contentTable = ContentTable::getInstance();

However, what really happens is that first PageTable::getInstance() is called and since PageTable itself doesn’t have a method defined as getInstance() the parent method is called. This sets $instance as a reference to the newly created object. However, the $instance property belongs to DataTable and not to PageTable. Even declaring a $instance property local to PageTable has the same result as in this case self::$instance refers to the parent class (which is where the method is run from). Thus when ContentTable::getInstance() is called, the value of self::$instance is detected as being set and the original instance of PageTable is returned. This is obviously not the intention.

The only way around this is to duplicate code by adding an $instance property to each subclass, as well as a duplicate of the getInstance() method.

As an aside, the same is also true of class constants which are also referred to with the self:: caller. From this we can infer that self:: always refers to the context of the current code block not the class from which a method is called.

Leave a Reply

Your email address will not be published. Required fields are marked *