Singleton question

I have created a singleton class but what is the best to have many objects singleton as well?

For example:

$this->registry = registry::instance();

$this->registry->set(‘A’,new Database);
$this->registry->set(‘B’,new Database);
$this->registry->set(‘C’,new Database);

as you can see I have many Database objects but its not singleton


class registry
{
    private static $instance = null;
    private static $objects = array();
    
    private function __construct() { }
    public function __clone() { }
    
    public function instance()
    {
        if (!isset(self::$instance))
        {
            self::$instance = new self();
            return self::$instance;
        }
    }

   static public function set($name, $value)
    {
        self::$objects[$name] = $value; 
    }
}


class Database
{
    function __construct() { }
}

I need a feedback please… singleton class stores list of objects and Database object become singleton.


class Database
{
    function __construct() { }
   
    private static $db_setting;
    private static $instance;
   
    public static function instance()
    {
        if ( ! self::$instance )
        {
            self::$instance = new self();
        }
      
        return self::$instance;
       
    }



 $this->registry->set("A",Database::instance());

By definition, you can’t have many singleton objects from one singleton class. A singleton is a design pattern when you want to restrict instantiation of a class to one object (ie a single object).

Sorry, I have not made myself clear.

If you look at my second post, is this the best way doing it?

In you second post, you should declare you constructor private to be absolutely certain of a singleton. That way client code has to use your static method to instantiate the object.

In your current code,


$obj = new Database();

would allow creation of a separate Database object.

Note that singleton has many flaws, and isn’t really a recommended style of application design.

Mentioned on Wikipedia, views I agree with:

Drawbacks

It should be noted that this pattern makes unit testing far more difficult[URL=“http://en.wikipedia.org/wiki/Singleton_pattern#cite_note-googletesting.blogspot.com-5”][6], as it introduces [URL=“http://en.wikipedia.org/wiki/Global_variables”]global state into an application.

Advocates of dependency injection would regard this as an [URL=“http://en.wikipedia.org/wiki/Anti-pattern”]anti-pattern, mainly due to its use of private and static methods.

I’m a big advocate of both unit testing and dependency injection, as are many PHP application developers.

Of course, you’re welcome to make your application in any way you wish - I’m just curious as to why you’d choose Singleton.

I am developing basic MVC framework, I decided to use Singleton for db classes, authentication class, etc.

What you would recommend apart from Singleton? Example of pattern would be good.

Cheers

Singleton is good for DB class, use it!
Just don’t mention that you use singleton on this forum, you will be lectured by the ‘dependency injection’ fans for sure. I was just waiting to see how long it would take for the first anti-singleton post to appear, and sure enough, it did not take long.

Does cakephp, CI and other major open source projects use Singleton ?

Take a look here: http://www.sitecrafting.com/blog/php-patterns-part/

For the DB, I use a STATIC class for my projects.

But, it’s true, testing can be a bit difficult with static/singletons. Since you will need an extra if test mode in there. But if you don’t use it, you will have to pass the damn DB connection everywhere. And after that, the session object, the error object and so on…

So, in my projects, I have a few classes (DB, Log, Session, Messaging, Benchmark) that are static singletons. It just makes everything much simpler and less typing.

For unit testing, i just include different configuration/class files, that would create different objects.

Post about using Register Globals and you’ll have the same thing. Any non-best-practise approach will cause controversy.

Singleton isn’t exactly the evil of evils, however it has certain problems which you will certainly come across. If you use it across the whole website, there will be a point where you come to a few stumbling blocks. For example - what if you want a model to extract data from a selection of databases, based on some credentials, but the rest of the models to load from one specific one? What if you want a module to load with a slightly different configuration from the rest of the page?

Dependency injection is surprisingly similar to singleton, the only difference being that rather than the whole global application accessing the objects. I use an ‘Application’ object which I pass to each object which requires access to request information, settings or the database.

I DO have a static function which loads the default configuration, but that is used solely in the initiation phase and can be ignored by loading the objects manually.

Here’s an example using only Database and Request objects in the application class:

class Application{
    protected $_Database, $_Settings, $_Request;
    function getDatabase(){ return $this->_Database; }
    function getRequest(){ return $this->_Request; }
    function getSettings(){ return $this->_Settings; }
    function setDatabase(Database $Database){ $this->_Database =  $Database; }
    function setRequest(Request $Request){ $this->_Request =  $Request; }
    function setSettings(Settings $Settings){ $this->_Settings = $Settings; }
    static function getDefault(){
        $Application = new Application();
        $Application->setSettings(Settings::getDefault($this));
        $Application->setDatabase(MySQLDatabase::getDefault($this));
        $Application->setRequest(Request::getDefault($this));
    }
}
class Settings{
    protected $_Settings = array();
    function getSetting(){
        $Path = func_get_args();
        $Current = $this->_Settings;
        foreach($Path as $P){
            if(array_key_exists($P, $Current)){
                $Current = $Current[$P];
            }else{
                return false;
            }
        }
        return $Current;
    }
    function loadFromIniFile($FileName){
        if(file_exists($FileName)){
            $this->_Settings = parse_ini_file($FileName, true);
        }
    }
    static function getDefault(Application $Application){
        $Settings = new Settings();
        $Settings->loadFromIniFile(parse_ini_file('Configuration/Settings.ini', true));
        return $Settings;
    }
}
class MySQLDatabase implements Database{
    protected $_PDO;
    function __Construct($Host, $Database, $Name, $Password);
    function select($TableName, array $Clause = array(), $OrderBy =  null, $Limit = null);
    function update($TableName, array $Data, array $Clause);
    function insert($TableName, array $Data);
    function remove($TableName, array $Clause, $Limit = null);
    function getDefault(Application $Application){
        $Settings = $Application->getSettings();
        $Host = $Settings->getSetting('MySQL', 'Host');
        $Database = $Settings->getSetting('MySQL', 'Database');
        $Name = $Settings->getSetting('MySQL', 'Name');
        $Password = $Settings->getSetting('MySQL', 'Password');
        if($Host !== false && $Database !== false && $Name !== false && $Password !== false){
            $MySQL = new MySQLDatabase($Host, $Database, $Name, $Password);
            return $MySQL;
        }else{
             //produce error
        }
    }
}
class Request{
    protected $_SuperGlobals, $_URI;
    function getDefault(Application $Application){
        //you get the point :P
    }
}

You then pass $Application through the constructor of any object that needs database access etc.

The benefit comes from when you want to load a module as if it’s meant to be on its own request. You can create a clone of $Application, but change that specific Request object’s URI to request something else - within the same application as another request. This means you can load a plugin with something like:


$Clone = new Application();
$Clone->setSettings($Application->getSettings());
$Clone->setDatabase($Application->getDatabase());
$FalseRequest = new Request();
$FalseRequest->setURI('Content', 'Menu');
$FalseRequest->setSuperGlobals(array('Session' => $Application->getRequest->getSession())); //post and get default to blank arrays
$Clone->setRequest($FalseRequest);
$Menu = new ExternalModule($Clone);

That, of course, is a trivial example, but there are huge benefits to using different instantiations of objects. If you want to use singleton, you may as well not be using objects at all.

Edit:

For a better example, take a look at my post (the last post) on the following thread: http://www.sitepoint.com/forums/showthread.php?t=666727

Not sure about these, but Zend uses it.

I have never used the Zend Framework - but I’ve seen in discussions that Singleton was used in older versions of the framework but not more recent - though I can’t back that up.

Can you give an example of the singleton code used with the Zend framework?