OO and "Singleton" class

OO and "Singleton" class

am 01.09.2009 23:16:03 von Paul M Foster

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

Re: OO and "Singleton" class

am 02.09.2009 00:06:24 von Eddie Drapkin

On Tue, Sep 1, 2009 at 5:16 PM, Paul M Foster wrot=
e:
>
> I'm a little fuzzy on some of the PHP implementation details for some
> stuff. In PHP (5 <=3D 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 =3D $co=
nfig;
>            }
>            else
>                self::$cfg =3D arr=
ay();
>        }
>    }
>
>    // 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 =3D true)
>    {
>        $write =3D false;
>        if (array_key_exists($index, self::$cfg) and $=
overwrite)
>            $write =3D true;
>        elseif (!array_key_exists($index, self::$cfg))
>            $write =3D true;
>        if ($write) {
>            self::$cfg[$index] =3D $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 =3D new Singleton; //replace Singleton with class na=
me

return self::$instance;
}

public function __clone() {
throw new Exception('Cannot clone a Singleton');
}
}

This class "shell" will prevent people from instantiating it ($foo =3D
new Singleton is an error). Instead, deployment will look like `$foo
=3D Singleton::getInstance()` which, as you can tell, always returns the
same instance. Throwing an exception out of __clone() will prevent
something like `$foo =3D Singleton::getInstance(); $bar =3D 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;
=09
private function __construct() {
if(!is_array(self::$cfg)) {
if(defined('CFGFILE')) {
include(CFGFILE);
self::$cfg =3D $config;
} else {
self::$cfg =3D array();
}
}
}
=09
public function getInstance() {
if(!(self::$instance instanceof config)) {
self::$instance =3D new config();
}
=09
return self::$instance;
}
=09
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 =3D true) {
$write =3D false;
if (array_key_exists($index, self::$cfg) and $overwrite) {
$write =3D true;
} elseif (!array_key_exists($index, self::$cfg)) {
$write =3D true;
}
=09
if ($write) {
self::$cfg[$index] =3D $value;
return true;
} else {
return false;
}
}
=09
=09
}

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

Re: OO and "Singleton" class

am 02.09.2009 06:45:00 von Paul M Foster

On Tue, Sep 01, 2009 at 06:06:24PM -0400, Eddie Drapkin wrote:

> On Tue, Sep 1, 2009 at 5:16 PM, Paul M Foster 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.)



>
> 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:

Good explanation. Thanks. I'll try it out.

Paul

--
Paul M. Foster

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Re: OO and "Singleton" class

am 02.09.2009 07:02:25 von KOYAMA Tetsuji

Hi,

After PHP 5.3, there is better implements for Singleton.

http://d.hatena.ne.jp/Yudoufu/20090811/1250021010

This entry was written by Japanese, but you may understand php code. :-)

On Wed, Sep 2, 2009 at 07:06, Eddie Drapkin wrote:
> On Tue, Sep 1, 2009 at 5:16 PM, Paul M Foster 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
>
>



--
$B>.;3E/;V!w%F%C%/%9%?%$%k(B
koyama@techstyle.jp : http://techstyle.jp/
koyama@hoge.org : http://d.hatena.ne.jp/koyhoge/

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php