tags:

views:

151

answers:

4

Hi, I am going to use singleton classes to manage both DB connections and references to application settings.

It seems a little messy to have to use the following code in every method in order to access the db class.

$db = DB::getInstance();

Is there a more efficient way of going about it?

Any advice appreciated.

Thanks

A: 

It is not messy. This is an intended behavior of Singletons. And, actually, this is just one line of code. Do you wish to make it even more compact? :)

FractalizeR
I just didn't want to repeat the line at the start of every single method that required it. I had considered adding it to the constructor but was not sure if this was considered good practice.
Dan
The "risk" of adding to the constructor is, that you also get the Singleton, when you don't need it - can be unhandy in some cases. If the class is clever, it will not start a DB connection when there is no queries, but if not, you get an overhead.
smint
A: 

My preferred method is to create a Base class which all the classes that need db access descend from. Base calls the singleton(s) in its constructor. All its children call their parent constructor. e.g.:

class Base {
  protected $db;

  public function __construct(){
    $this->db = DB::getInstance();
  }
}

class Achild extends Base {
  protected $var1;

  public function __construct($arg){
     parent::__construct();
     $this->var1=$arg;
  }
}
dnagirl
A: 

I often use the Registry pattern, where this behavior occurs as well. I always set a instance variable in the constructor of my models to point to the Registry entry;

class Registry {
    private static $_instance;
    private $_registry;

    private function __construct() {
     $_registry = array();
    }

    public static function getInstance() {
     if (!Registry::$_instance) {
      Registry::$_instance = new Registry();
     }

     return Registry::$_instance;
    }

    public function add($key, &$entry) {
     $this->_registry[$key] = &$entry;
    }

    public function &get($key) {
     return $this->_registry[$key];
    }

    public function has($key) {
     return ($this->get($key) !== null);
    }
}

Model example;

class MyModel {
    private $_db;
    public function __construct() {
        $this->_db = Registry::getInstance()->get('dbKey');
    }

    /* Every function has now access to the DAL */
}

Instantiation example;

$dal = new Db(...);
Registry::getInstance()->add('dbKey', $dal);
...
$model = new MyModel();
$model->doDbStuff();

Another approach is to always pass the reference as a parameter to each constructor.

Of course I only use this behavior when most of the methods in my model use the reference, if only a few (one or two) methods have use of the reference, I call the Registry/Singleton like you showed.

Björn
A: 

I know what you mean... hate that ::getInstance() stuff! So go and use static methods:

class DB {
    private static $db;

    public static function getInstance() {
     if(!self::$db) {
      self::$db = new DBconnector();
     }
    }

    public static function query($query) {
     return self::$db->query($query);
    }
}

Usage is much nicer:

$result = DB::query('SELECT whatever;');

And if you use PHP 5.3 you can write a __callStatic similar to this, to forward all the method calls to the object:

public static function __callStatic($method, $args) {
    call_user_func_array(array(self::$db, $method), $args);
}

And to make me happy, add an __autoloader so that you can access DB without any worries any time!

smint