Is it a bad idea to create a global database object? Am I just being lazy?Global objects are typically seen as a bad practice. There are a few ways to get around them.
You could make the database object a singleton, but singletons are also typically seen as a bad practice since it is easy to misuse them.
You could pass the database object around the application to the objects that need it, but depending on the application's architecture, this could get pretty ridiculous as you could end up with objects that have the database object but don't actually use it and just pass it on. If the architecture is well suited to this, then this is a good option. But for example if the architecture is fairly modular, then this would get rather silly to do.
You could also make a Registry or Service Locator and get the database object that way. I tend to prefer using a Registry in cases where the object may be needed in several locations, such as a database object would be.
A simple example of a Registry would be:
// set the database object to the registry (after it is created)
ObjectRegistry::set('db', $db);
// where you need the database object, you do
$db = ObjectRegistry::get('db');
I also like my registry to be able to create the object on its own so that it is only created when & if it is required. You can use the create_function() function to do this. Here is an example of how I register my db object:
ObjectRegistry::registerConstructor('db', create_function('', '
$db = new DbDriverProxy();
// Connect to the database
$db->connect("connection string");
// return db object
return $db;
'));
If you don't like using create_function(), you can also make a normal function and pass that in, such as:
function create_db_object() {
$db = new DbDriverProxy();
// Connect to the database
$db->connect("connection string");
// return db object
return $db;
}
ObjectRegistry::registerConstructor('db', 'create_db_object');
In this case, the database object isn't actually created until the first time I call ObjectRegistry::get('db');.
Here is my ObjectRegistry code also, to take a look at. Feel free to use it:
class ObjectRegistry {
private static $store = array();
public function __construct() {
throw new Exception(
'Cannot initiate a new instance on a registry class. Use "' . __CLASS__ . '::method();" instead '
);
}
public static function isValid($key) {
return array_key_exists($key, self::$store);
}
public static function get($key) {
$return = null;
if (self::isValid($key)) {
$return = self::$store[$key];
// a constructor
if (is_array($return) && isset($return['constructor'])) {
$return = $return['constructor']();
self::set($key, $return);
}
}
return $return;
}
public static function set($key, $object) {
self::$store[$key] = $object;
}
public static function registerConstructor($key, $function) {
self::$store[$key] = array('constructor' => $function);
}
}Wow, that is a really good answer. Thank you so much for taking the time to write it out.
You could pass the database object around the application to the objects that need it, but depending on the application's architecture, this could get pretty ridiculous[...]
This is how I had been doing it before and as you say, it can get very ridiculous.
I really like the idea of the registry. That's all new to me. I'll go and check it out.
Thanks again!
DougalWow, that is a really good answer. Thank you so much for taking the time to write it out.
I join with you
You could make the database object a singleton, but singletons are also typically seen as a bad practice since it is easy to misuse them.
You could pass the database object around the application to the objects that need it, but depending on the application's architecture, this could get pretty ridiculous as you could end up with objects that have the database object but don't actually use it and just pass it on. If the architecture is well suited to this, then this is a good option. But for example if the architecture is fairly modular, then this would get rather silly to do.
You could also make a Registry or Service Locator and get the database object that way. I tend to prefer using a Registry in cases where the object may be needed in several locations, such as a database object would be.
A simple example of a Registry would be:
// set the database object to the registry (after it is created)
ObjectRegistry::set('db', $db);
// where you need the database object, you do
$db = ObjectRegistry::get('db');
I also like my registry to be able to create the object on its own so that it is only created when & if it is required. You can use the create_function() function to do this. Here is an example of how I register my db object:
ObjectRegistry::registerConstructor('db', create_function('', '
$db = new DbDriverProxy();
// Connect to the database
$db->connect("connection string");
// return db object
return $db;
'));
If you don't like using create_function(), you can also make a normal function and pass that in, such as:
function create_db_object() {
$db = new DbDriverProxy();
// Connect to the database
$db->connect("connection string");
// return db object
return $db;
}
ObjectRegistry::registerConstructor('db', 'create_db_object');
In this case, the database object isn't actually created until the first time I call ObjectRegistry::get('db');.
Here is my ObjectRegistry code also, to take a look at. Feel free to use it:
class ObjectRegistry {
private static $store = array();
public function __construct() {
throw new Exception(
'Cannot initiate a new instance on a registry class. Use "' . __CLASS__ . '::method();" instead '
);
}
public static function isValid($key) {
return array_key_exists($key, self::$store);
}
public static function get($key) {
$return = null;
if (self::isValid($key)) {
$return = self::$store[$key];
// a constructor
if (is_array($return) && isset($return['constructor'])) {
$return = $return['constructor']();
self::set($key, $return);
}
}
return $return;
}
public static function set($key, $object) {
self::$store[$key] = $object;
}
public static function registerConstructor($key, $function) {
self::$store[$key] = array('constructor' => $function);
}
}Wow, that is a really good answer. Thank you so much for taking the time to write it out.
You could pass the database object around the application to the objects that need it, but depending on the application's architecture, this could get pretty ridiculous[...]
This is how I had been doing it before and as you say, it can get very ridiculous.
I really like the idea of the registry. That's all new to me. I'll go and check it out.
Thanks again!
DougalWow, that is a really good answer. Thank you so much for taking the time to write it out.
I join with you