PHP Singleton

I recently had a bad deer-in-the-headlights moment over a simple Singleton pattern. In an effort to turn a negative into a positive, and to burn something new (it never occurred to me that it was necessary to implement the __clone() magic method) into my feeble memory, here’s an implementation of Singleton in PHP, along with a couple of unit tests.

Of course, Singleton is still just another name for global variable.

 
/**
 * EmptySingleton
 *
 * Does nothing, but only one of it can exist at a time
 *
 * @version $Id$
 */
class EmptySingleton
{
    private static $_self = null;
 
    /**
     * EmptySingleton::init()
     *
     * Create an instance of EmptySingleton if necessary, and return it
     *
     * @access public
     * @return EmptySingleton
     */
    public static function init()
    {
        if ( self::$_self == null )
        {
            self::$_self = new EmptySingleton();
        }
 
        return self::$_self;
    }
 
    /**
     * EmptySingleton::__construct()
     *
     * The only place this can be called from is EmptySingleton::init()
     *
     * @access private
     */
    private function __construct()
    {
    }
 
    /**
     * EmptySingleton::__clone()
     *
     * If this somehow manages to get itself called, it throws an error
     *
     * @access private
     * @throws Exception
     */
    /** @codeCoverageIgnoreStart */
    private function __clone()
    {
        throw new Exception();
    }
    /** @codeCoverageIgnoreEnd */
}
 
class EmptySingletonTest extends PHPUnit_Framework_TestCase
{
    public function testCanInit()
    {
        $this->_obj = EmptySingleton::init();
        $this->assertTrue( $this->_obj instanceof EmptySingleton );
    }
 
    public function testOnlyOneInstance()
    {
        $instance_one = EmptySingleton::init();
        $instance_two = EmptySingleton::init();
 
        $instance_one->temp = 42;
 
        $this->assertEquals( $instance_one->temp, $instance_two->temp );
    }
}
 
$suite = new PHPUnit_Framework_TestSuite( 'EmptySingletonTest' );
PHPUnit_TextUI_TestRunner::run( $suite );

Update: Poking around online, I came across this interesting singleton implementation. He’s using class variables rather than instance variables, meaning that every instance of the class shares the same state. As thread safety isn’t really an issue in PHP it will work, but I think forcing class users to avoid the constructor offers a useful hint that something unusual’s going on with that class.

Tags: ,

  1. Tommy’s avatar

    So does a singleton just restrict one implementation from each person accessing it or one all together? I am not using sessions.