Categories
Posts

Extendable Singleton Base Class for PHP

I’ve been thinking about singletons in PHP recently. There is an example in the PHP docs, which works well enough. Then I started looking for a way to have a singleton base class. My first few attempts failed, the key was to leverage late static binding, which was added in PHP 5.3.0.

[sourcecode lang=”php”]
class Singleton {
protected static $instance;

private function __clone() { }
private function __construct() { }
private function __wakeup() { }

final public static function singleton() {
if ( !isset( static::$instance ) ) {
static::$instance = new static();
}

return static::$instance;
}
}
[/sourcecode]

This base class can be extended to create simple singleton classes, like so:

[sourcecode lang=”php”]
class Example extends Singleton {
protected static $count;

public function add( $num = 1 ) {
$this->count += $num;
return $this->count;
}

public function get_count() {
return $this->count;
}

public function subtract( $num = 1 ) {
$this->count -= $num;
return $this->count;
}
}
[/sourcecode]

Here is what this looks like in action:

[sourcecode lang=”php”]
echo "COUNT:n";
$count = Example::singleton();
echo $count->add() . "n"; // 1
echo $count->add( 4 ) . "n"; // 5
echo $count->subtract( 7 ) . "n"; // -2
echo $count->add( 10 ) . "n"; // 8
echo $count->get_count() . "n"; // 8
echo "n";

echo "ANOTHER:n";
$another = Example::singleton();
echo $another->get_count() . "n"; // 8
echo $another->add( 2 ) . "n"; // 10
echo $another->subtract( 3 ) . "n";// 7
echo $another->get_count() . "n"; // 7
echo "n";
[/sourcecode]

There are a few actions that the singleton class specifically fobids:

[sourcecode lang=”php”]
// Each of these will throw an error
$test = new Example();
$test = clone $count;
$test = unserialize( serialize( $count ) );
[/sourcecode]

You could also do this via traits if you are using PHP 5.4.0 or newer. I wish PHP 5.0.0 had just gone with multiple inheritance in the first place.

One reply on “Extendable Singleton Base Class for PHP”

class Example1 extends Singleton {}
class Example2 extends Singleton {}

var_dump(Example1::singleton() === Example2::singleton()); // boolean true
print_r(get_class(Example2::singleton())); // IRRViewParserExample1

Leave a Reply

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