Jump to content

Simple OOP question: best practice for site-wide constants


johnsmith153

Recommended Posts

DatabaseConnection would in this case be a Singleton, and would support multiple connection instances (for a multi-database application).

 

The correct term would then be Multiton not Singleton. IMO you should avoid static methods when not necessarily needed, they create a not so easy to replace dependency on your code.

True enough!  In my last example, ConnectionManager would be a hacked up Multiton of sorts (though returns DC instances), and DatabaseConnection, well, not really well defined.  Not a well thought-out design... could be improved on a lot.    Ideally, they would be merged into one Multiton.

 

The point of my post was to give an example of how to design classes that use environment variables so they aren't dependent upon them.  Obviously, it's an iterative process, and the final result should involve more planning than can be done in a forum post.

 

Link to comment
Share on other sites

Since I'm obsessive about my code, here's an improvement on my ConnectionManager class design above, using a standard Multiton pattern to extend the PDO class:

<?php
// PDOManager class as an extension of PDO
class PDOManager extends PDO {
private static $connections = array();

private __construct($config) {
	// Define the DSN from the config
	$dsn = "{$conn['type']}:host={$conn['host']}";
	if ($conn["dbname"]) $dsn .= ";dbname={$conn['dbname']}";
	if ($conn["port"]) $dsn .= ";port={$conn['port']}";

	// super() to the PDO constructor
	parent::__construct($dsn, $conn["user"], $conn["pass"], $conn["driver_options"]);
}

public static function addConfig(array $config, $connection_name=null) {
	// If no connection name was provided, use an indexed reference
	if (is_null($connection_name)) 
		$connection_name = count(self::$connections);

	// Create a DB config
	self::$connections[$connection_name] = array(
		"type" => isset($config["type"]) ? $config["type"] : "mysqli",
		"host" => isset($config["host"]) ? $config["host"] : "localhost",
		"user" => isset($config["user"]) ? $config["user"] : null,
		"pass" => isset($config["pass"]) ? $config["pass"] : null,
		"dbname" => isset($config["dbname"]) ? $config["dbname"] : null,
		"port" => isset($config["port"]) ? (int) $config["port"] : null,
		"driver_options" => is_array($config["driver_options"]) ? $config["driver_options"] : array(),
		"handler" => null
	);
}

public static function getInstance($connection_name=null) {
	// In case soemone wants to use as a singleton, just get the first index
	if (is_null($connection_name)) $connection_name = 0;


	// Check if this connection config exists
	if (!isset(self::$connections[$connection_name]))
		throw new Exception("Invalid connection provided.");

	// Instantiate the connection by reference for reuse later
	$config =& self::$connections[$connection_name];
	if (is_null($config["handler"])) {
		$config["handler"] = new __CLASS__($config);
	}

	// Return the PDOManager instance
	return $config["handler"];
}

}
?>

 

And in use:

<?php
// Define a PDOManager config from our environment settings
// Only have to do this one time
$config = array(
"host" => Config::read("database.main.host"),
"user" => Config::read("database.main.user"),
"pass" => Config::read("database.main.pass"),
"dbname" => Config::read("database.main.dbname")
);
PDOManager::addConfig($config, "main");


// Get a connection for use
$conn = PDOManager::getInstance("main");
$conn->query("SELECT * FROM whatever");

?>

 

This class should actually work, independently of any environment variables.

 

And the "in use" example snippet will work too (given that you have a functioning Config class).

 

Hope it explains how I feel environment variables are best used in classes.

Link to comment
Share on other sites

In the case of this example, using a Singleton (or Multiton) allows you to persist a connection for use across your application.

 

I know many aren't a fan of the Singleton pattern, but it's a nice way of handling connection persistence with a clean interface.

 

Anyhow, the Singleton pattern isn't what I was trying to explain here, but the use of environment variables. 

 

Discussion of the merits of a Singleton can fill a discussion by itself.

Link to comment
Share on other sites

In the case of this example, using a Singleton (or Multiton) allows you to persist a connection for use across your application.

 

Not a valid argument since I can do the same thing with simple objects and a clever architecture.

 

I said "with a clean interface".  "Clever architecture" is usually unnecessarily complex. 

 

Nevertheless, it's an ongoing argument with no clear winner. 

 

It's a matter of preference.  And not pertinent to this thread. 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.