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.