I did think of another issue in this class. What if you want to pass in parameters on construction of a Singleton class? I'd argue against doing this as a Singleton is supposed to control its own construction, however it is possible to do:
PHP Code:
// The sole access point for singletons.
final public static function & GetInstance( $inClass )
{
// Do we have one yet?
if( !array_key_exists( $inClass, self::$gInstances ) )
{
self::$gInstances[$inClass] =& new $inClass;
// Is this a singleton class?
if( !( self::$gInstances[$inClass] instanceof Singleton )
|| $inClass == 'Singleton' )
{
unset( self::$gInstances[$inClass] );
throw new Exception( "$inClass is not a Singleton class." );
}
// Get any extra arguments if any.
$theArguments = func_get_args();
// Remove the class name from the list.
array_shift( $theArguments );
// Call construct with any extra arguments passed in.
call_user_func_array
( array( self::$gInstances[$inClass], 'Construct' ),
$theArguments );
}
return self::$gInstances[$inClass];
}
We get the function arguments using func_get_args(). We then remove the first argument (this will be the class name). We then use call_user_func_array() to call the function and pass in any extra parameters passed into this function.
So with this test script:
PHP Code:
<?php
include_once( $_SERVER['DOCUMENT_ROOT'].'/../Include/Singleton.php' );
// A test singleton with a 'Constructer'
class TestSingleton extends Singleton
{
function Construct( $inVar1 = null, $inVar2 = null )
{
echo <<<_TEXT_
Constructing...<br />
Var1 = $inVar1<br />
Var2 = $inVar2<br />
<br />
_TEXT_;
}
public $mVar;
}
// Instantiate the Test Singleton.
$theTestSingleton = Singleton::GetInstance( 'TestSingleton', 'Hello,', 'World!' );
?>
We get this output:
Quote:
Constructing...
Var1 = Hello,
Var2 = World!
|
A caveat is in order though: this kind of Singleton is created on first access. In more complicated scripts it can be difficult to determine exactly when a Singleton will be constructed.
Always ensure that Singleton constructors have default values for all their parameters to prevent any warnings. Personally I'd choose to design my Singletons so they handle their own construction, which is kind of the point of Singletons anyway.