OOP Pattern search

looking for a suitable DB Pattern

  • (2 Pages)
  • +
  • 1
  • 2

23 Replies - 2569 Views - Last Post: 13 September 2010 - 05:06 AM

#1 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3577
  • View blog
  • Posts: 10,442
  • Joined: 08-June 10

OOP Pattern search

Posted 03 August 2010 - 10:59 AM

Hi Guys,

I recently read about the Abstract Singleton and it made me wonder, how I could do a DB implementation, which (unlike the Singleton) would allow several predefined DB connections. (I have the distinct feeling, that a Factory Pattern might be involved).

So, would you share your ideas, how to do that?

PS. the DB connections are done in PDO.

This post has been edited by Dormilich: 03 August 2010 - 11:02 AM

Is This A Good Question/Topic? 0
  • +

Replies To: OOP Pattern search

#2 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10816
  • View blog
  • Posts: 40,316
  • Joined: 27-December 08

Re: OOP Pattern search

Posted 03 August 2010 - 12:24 PM

I couldn't find any evidence of formal Enums being used in PHP, but that might be the route to go. Create x instances of your class as static variables in the class, provide access to them, and make the constructor private or protected.

I found this link going into more detail: http://blog.agilephp...t-enums-in-php/
Was This Post Helpful? 0
  • +
  • -

#3 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3577
  • View blog
  • Posts: 10,442
  • Joined: 08-June 10

Re: OOP Pattern search

Posted 03 August 2010 - 01:08 PM

is that Enum something like a SplFixedArray or SplObjectStorage? (I didnít understand the enum thing Ö)
Was This Post Helpful? 0
  • +
  • -

#4 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10816
  • View blog
  • Posts: 40,316
  • Joined: 27-December 08

Re: OOP Pattern search

Posted 03 August 2010 - 01:17 PM

In a number of languages like Java, SQL, etc., there are types called Enumerated Data Types. In SQL, you can declare enum types with x values. In Java, enums are classes with only certain instances defined with the class. So if you are familiar with Java syntax, here is an example:
enum Day{

   SUNDAY("SUNDAY"),
   MONDAY("MONDAY"),
   //continued to Saturday
   SATURDAY("SATURDAY");

   String name; 

   Day(String s){
      name = s;
   }

}


These constants are the only instances of Day in existence. As I couldn't find examples of formal enums like this in PHP, you could put together a class to do the same thing. Define the class, and instantiate n static variables when the class is declared, and don't allow any more to be created. This is more or less the concept of enums without formally using enums, as PHP doesn't have an enum reserved word.
Was This Post Helpful? 0
  • +
  • -

#5 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3577
  • View blog
  • Posts: 10,442
  • Joined: 08-June 10

Re: OOP Pattern search

Posted 03 August 2010 - 02:14 PM

I think Iím slowly getting it.

ah, and Iím not familiar with Java at all.
Was This Post Helpful? 0
  • +
  • -

#6 Valek  Icon User is offline

  • The Real Skynet
  • member icon

Reputation: 543
  • View blog
  • Posts: 1,713
  • Joined: 08-November 08

Re: OOP Pattern search

Posted 03 August 2010 - 06:43 PM

This is the best current implementation I have found so far for enums in PHP: Link.
Was This Post Helpful? 0
  • +
  • -

#7 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3577
  • View blog
  • Posts: 10,442
  • Joined: 08-June 10

Re: OOP Pattern search

Posted 03 August 2010 - 10:56 PM

ok, back from Enum to implementation, what would be the way to go?
Was This Post Helpful? 0
  • +
  • -

#8 alienDeveloper  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 27
  • Joined: 11-November 08

Re: OOP Pattern search

Posted 04 August 2010 - 02:36 AM

Hi Dormilich,

I am guess that, what you want to do is

You have multiple databases which you want to connect to at the same time, and at the same time you want only one connection to each databases.

I had a similar system in one of my works. What i wanted to do is, i implemented a multiple database system where i need to connect at the same time. And my problem was i will be able to connect to the main database without any problem but to know which secondary databases i need to connect i need to have some values which i will get only one some classes. So i was forced to connect to those databases from inside the classes and at times i wanted to use some of these classes together making multiple connections to the same database.

Here i how i solved it using Singleton class.

<?php

	include_once 'MultiDatabase.class.php';

	class MultipleDatabase{
		
		public $resources;
		
		static $instance;
		
		private function __construct(){
			//singleton class needs private constructor.
		}
		
		public static function init(){
			if ( MultipleDatabase::$instance == NULL ){
				MultipleDatabase::$instance = new MultipleDatabase();
			}
			
			$instanceReferance =& MultipleDatabase::$instance;
			
			return $instanceReferance;
		}
		
		public function initDB ($project_id){
			$id = $this -> calculateD($project_id);
			if ( !isset ( $this -> resources [$id])) $this -> resources[$id] = new MultiDatabase($id, true); 
			//else op ( $id . "not created" );
			$resourcesReferance =& $this -> resources [$id];
			
			return $resourcesReferance;
		}
		
		private function calculateD ($project_id){
			// calculate the id of db which the project is in and return it.
		}
	}

?>



And in the MultiDatabase class i will fetch the db details of the database corresponding to the id and create a new PDO connection.

Hope this helps.

Edit:
How you init the db is
$newMD = MultipleDatabase::init();
$this -> secondaryDB = $newMD -> initDB ($project_id );


Regards,

This post has been edited by alienDeveloper: 04 August 2010 - 02:38 AM

Was This Post Helpful? 0
  • +
  • -

#9 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3577
  • View blog
  • Posts: 10,442
  • Joined: 08-June 10

Re: OOP Pattern search

Posted 04 August 2010 - 03:01 AM

View PostalienDeveloper, on 04 August 2010 - 09:36 AM, said:

I am guess that, what you want to do is

You have multiple databases which you want to connect to at the same time, and at the same time you want only one connection to each databases.


what I ultimately want, is to use a simple API for database calls, even if I need 2 (or more) DB connections in parallel.

to demonstrate what I’m after, I’ll show you the current state with a single connection
abstract class aDBC implements DBStatement
{
	private static 
		$PDO     = NULL,
		$DB_NAME = DB_NAME
	;

	private static function connect()
	{
		if (NULL === self::$PDO)
		{
			$dsn = 'mysql:host=' . DB_SERVER . ';dbname=' . self::$DB_NAME;
			self::$PDO = new PDO($dsn, DB_USER, DB_PASS);
			self::$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
		}
	}

	public static function prepare(
		$sql
	)
	{
		self::connect();
		return self::$PDO->prepare($sql);
	}

	# and some more methods

}

class DBPS extends DBR implements IteratorAggregate, DBHandler
{
	public function __construct(
		$sql
	)
	{
		$sql = preg_replace("@\s+@", " ", trim($sql));
		# this is where my "Singleton" kicks in
		$this->PS = aDBC::prepare($sql);
				
		if (!($this->PS instanceof PDOStatement))
		{
			$emsg = "Fehler bei der Erstellung des Prepared Statements.";
			throw new InitException(41, 0, __METHOD__, $emsg);
		}
	}

	public function execute(
		$input = array()
	)
	{
		# convert input to array or exit if type mismatch
		$param = $this->convert($input);
		# bind the values to the PS or exit if type mismatch
		$this->bind($param);
		# execute the PS
		$this->PS->execute();
		return $this;
	}

	# further methods

}


which results in easily maintainable calls:
$dbh = new DBPS("SELECT * FROM table WHERE `something` = ?");
$dbh->execute($value)->setFetchMode(DBR::FETCH_CLASS, "myOutputClass");

foreach ($dbh as $row)
{
	echo $row;
}


in the end, I want to retain the ease of calling, combined with the choice of the connection, without having to define the connection on code level (code re-usability).

This post has been edited by Dormilich: 04 August 2010 - 03:01 AM

Was This Post Helpful? 0
  • +
  • -

#10 alienDeveloper  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 27
  • Joined: 11-November 08

Re: OOP Pattern search

Posted 04 August 2010 - 03:44 AM

Hi,

Have you tried this?

	class DBConfigs{
		
		public static $databases = array (
									0 => array (
											"host" => "localhost",
											"db" => "test",
											"username" => "root",
											"password" => "password"
										),
									1 => array (
											"host" => "localhost",
											"db" => "test2",
											"username" => "root",
											"password" => "password"
										)
								);
		
	}
	
	abstract class aDBC implements DBStatement{
		private static 
			$PDO     = array(),
			$DB_NAME = DB_NAME
		;

		private static function connect($id){
			if (NULL === self::$PDO[$id]){
				$dsn = 'mysql:host=' . DBConfigs::$databases[$id]['host'] . ';dbname=' . DBConfigs::$databases[$id]['db'];
				self::$PDO[$id] = new PDO($dsn, DBConfigs::$databases[$id]['username'], DBConfigs::$databases[$id]['password']);
				self::$PDO[$id]->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
			}
		}

		public static function prepare( $sql, $id ){
			self::connect($id);
			return self::$PDO[$id]->prepare($sql);
		}

		# and some more methods

	}



class DBPS extends DBR implements IteratorAggregate, DBHandler{
	public function __construct( $sql, $id = 0 ){
		$sql = preg_replace("@\s+@", " ", trim($sql));
		# this is where my "Singleton" kicks in
		$this->PS = aDBC::prepare($sql, $id); 
				
		if (!($this->PS instanceof PDOStatement)){
			$emsg = "Fehler bei der Erstellung des Prepared Statements.";
			throw new InitException(41, 0, __METHOD__, $emsg);
		}
	}

	public function execute( $input = array() ){
		# convert input to array or exit if type mismatch
		$param = $this->convert($input);
		# bind the values to the PS or exit if type mismatch
		$this->bind($param);
		# execute the PS
		$this->PS->execute();
		return $this;
	}

	# further methods

}



$dbh = new DBPS("SELECT * FROM table WHERE `something` = ?", 1); // change the 1 to the id of the db u want to connect
$dbh->execute($value)->setFetchMode(DBR::FETCH_CLASS, "myOutputClass");

foreach ($dbh as $row){
	echo $row;
}




Please try this. i havn't run it. But i hope this works.

And by the way, you have an elegant way of writing the codes. ;)

Regards,
Was This Post Helpful? 0
  • +
  • -

#11 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3577
  • View blog
  • Posts: 10,442
  • Joined: 08-June 10

Re: OOP Pattern search

Posted 04 August 2010 - 03:52 AM

I want to avoid having to explicitly pass the connection ID with every call to aDBC::prepare(). I rather access the appropriate PDO object and then call the method.

more something like
class DBPS # Ö
{
	public function __construct($dbname, $sql)
	{
		$this->PS = DB::get($dbname)->prepare($sql);
	}
}

Was This Post Helpful? 0
  • +
  • -

#12 alienDeveloper  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 27
  • Joined: 11-November 08

Re: OOP Pattern search

Posted 04 August 2010 - 04:11 AM

Hi,

by id i didnt mean id itself, u can give any key to the DBConfig's database array like
class DBConfigs{
	
	public static $databases = array (
								"main" => array (
										"host" => "localhost",
										"db" => "test",
										"username" => "root",
										"password" => "password"
									),
								"secondary" => array (
										"host" => "localhost",
										"db" => "test2",
										"username" => "root",
										"password" => "password"
									)
							);
	
}




and use it like
$dbh = new DBPS("SELECT * FROM table WHERE `something` = ?", "main");



now that will allow you to avoid the sending id.

And you want to use as you said, here i will do it.

class DB{
		private static $POD = array();
		
		private static function get ($name){
			if ( NULL === self::$PDO[$name]){
				$dsn = 'mysql:host=' . DBConfigs::$databases[$name]['host'] . ';dbname=' . DBConfigs::$databases[$name]['db'];
				self::$PDO[$name] = new PDO($dsn, DBConfigs::$databases[$name]['username'], DBConfigs::$databases[$name]['password']);
				self::$PDO[$name]->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
			}
			
			$pdo =& self::$PDO[$name];
			return $pdo;
		}
	}


and use it like u said
class DBPS # Ö
{
	public function __construct($dbname, $sql)
	{
		$this->PS = DB::get($dbname)->prepare($sql);
	}
}




And again, i am not used to with PDO, i use my own DB Class which i worte. :) ..

So what you think?

Regards,
Was This Post Helpful? 0
  • +
  • -

#13 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3577
  • View blog
  • Posts: 10,442
  • Joined: 08-June 10

Re: OOP Pattern search

Posted 04 August 2010 - 04:12 AM

it doesn't matter, what type the connection ID is of, I just donít want to have it in the prepare() method.
Was This Post Helpful? 0
  • +
  • -

#14 alienDeveloper  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 27
  • Joined: 11-November 08

Re: OOP Pattern search

Posted 04 August 2010 - 04:19 AM

hi,

what about the second class the DB class? wont that work for you?
Was This Post Helpful? 0
  • +
  • -

#15 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3577
  • View blog
  • Posts: 10,442
  • Joined: 08-June 10

Re: OOP Pattern search

Posted 04 August 2010 - 05:15 AM

nope. well, not as it is written (DB has no public access). but I have now an idea how to tackle the problem.

thanks for your effort.

Dormi
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2