On Tue, Sep 1, 2009 at 5:16 PM, Paul M Foster<[email protected]> wrote:
>
> I'm a little fuzzy on some of the PHP implementation details for some
> stuff. In PHP (5 <= phpversion() < 5.3), I'd like a configuration class
> which can only effectively be instantiated once. Will the following code
> do this? Any other suggestions or corrections? (Code is untested. Feel
> free to complain about syntax.)
>
> class config
> {
> private static $cfg;
>
> // Initializes the configuration from main config file
> function __construct()
> {
> if (!is_array(self::$cfg)) {
> if (defined('CFGFILE')) {
> include(CFGFILE);
> self::$cfg = $config;
> }
> else
> self::$cfg = array();
> }
> }
>
> // Returns a config item or null if not found
> function item($index)
> {
> if (array_key_exists($index, self::$cfg))
> return self::$cfg[$index];
> else
> return null;
> }
>
> // Sets a config item, optionally overwriting.
> // Returns true on success, false on failure.
> function set($index, $value, $overwrite = true)
> {
> $write = false;
> if (array_key_exists($index, self::$cfg) and $overwrite)
> $write = true;
> elseif (!array_key_exists($index, self::$cfg))
> $write = true;
> if ($write) {
> self::$cfg[$index] = $value;
> return true;
> }
> else
> return false;
> }
>
> };
>
> Paul
>
> --
> Paul M. Foster
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>
The primary thing you need to do to make a class a singleton is
disallow the instantiation of a class directly. Which means using
visibility, which is conspicuously absent from your example above.
So, to prevent normal instantiation, we make the constructor private.
Also, we need a method to retrieve the instance. Static members serve
this purpose:
class Singleton {
private static $instance;
private function __construct() { }
public static function getInstance() {
if( ! self::$instance instanceof Singleton) //replace Singleton
with class name
self::$instance = new Singleton; //replace Singleton with class name
return self::$instance;
}
public function __clone() {
throw new Exception('Cannot clone a Singleton');
}
}
This class "shell" will prevent people from instantiating it ($foo =
new Singleton is an error). Instead, deployment will look like `$foo
= Singleton::getInstance()` which, as you can tell, always returns the
same instance. Throwing an exception out of __clone() will prevent
something like `$foo = Singleton::getInstance(); $bar = clone $foo;`
which is something I see overlooked a lot.
So, if you wanted to convert your full class to a singleton it would
look something like:
class config {
private static $instance;
private static $cfg;
private function __construct() {
if(!is_array(self::$cfg)) {
if(defined('CFGFILE')) {
include(CFGFILE);
self::$cfg = $config;
} else {
self::$cfg = array();
}
}
}
public function getInstance() {
if(!(self::$instance instanceof config)) {
self::$instance = new config();
}
return self::$instance;
}
public function __clone() {
throw new Exception("Cannot clone a Singleton.");
}
public function item($index) {
if(array_key_exists($index, self::$cfg))
return self::$cfg[$index];
else
return null;
}
// Sets a config item, optionally overwriting.
// Returns true on success, false on failure.
function set($index, $value, $overwrite = true) {
$write = false;
if (array_key_exists($index, self::$cfg) and $overwrite) {
$write = true;
} elseif (!array_key_exists($index, self::$cfg)) {
$write = true;
}
if ($write) {
self::$cfg[$index] = $value;
return true;
} else {
return false;
}
}
}
Note that this is also completely untested or anything of the sort.
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php