MelodyMaker Posted April 9, 2008 Share Posted April 9, 2008 Hi, I've just got into PHP Object-Oriented programming, and I wold like to ask to you the following question (I think, to many of you this is maybe a very stupid one): I have two classes: A Database class and a SessionManager class. So the question is quite simple: what is the best way to pass to SessionManager a DB instance? -passing it to the SessionManager constructor? $session = new SessionManager(Database::getInstance()); -passing it to a SessionManager method? $session = new SessionManager(); $DB = Database::getInstance() (suppose I use Singleton pattern) $session->loadDB($DB) or putting it directly INSIDE the SessionManager Object, maybe in its constructor: Class SessionManager{ private $DB; function __construct(){ $this->DB = Database::getInstance(); } } ... The questions comes from the fact that there will be many objects in my project and lots of them will use the DB object. I really don't know if there's a "best" solution. Maybe you can help. Thanks in advance. Davide Quote Link to comment Share on other sites More sharing options...
rhodesa Posted April 9, 2008 Share Posted April 9, 2008 I would just put it right in whatever function uses it.... Class SessionManager{ function __construct(){ } function updateUser ($data){ $db = Database::getInstance(); } } Quote Link to comment Share on other sites More sharing options...
keeB Posted April 10, 2008 Share Posted April 10, 2008 Is there an option D, None of the above? Look in to Data Access Objects (http://en.wikipedia.org/wiki/Data_Access_Object) http://www.phpfreaks.com/forums/index.php/topic,187289.msg839562.html#msg839562 Quote Link to comment Share on other sites More sharing options...
MelodyMaker Posted April 10, 2008 Author Share Posted April 10, 2008 Thank you. Here I found other informations about DAO: http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html It looks like a bit complicated to me, but I surely will consider it. Quote Link to comment Share on other sites More sharing options...
keeB Posted April 10, 2008 Share Posted April 10, 2008 Surely it's a bit complicated at first, but that's why you have us Go ahead and ask away and I'll be happy to clarify/help Quote Link to comment Share on other sites More sharing options...
MelodyMaker Posted April 11, 2008 Author Share Posted April 11, 2008 Thank you very much. Could you tell me please if the following one could be a correct solution: abstract class Database{ abstract protected function DBQuery($query,$line="",$file=""); abstract protected function DBfetchArray($mode=""); abstract static protected function DBgetInstance(); ... } class mysqliDB extends Database{ private function __construct()... //this should be a singleton static public DBgetInstance() ... //this returns only an Instance of this object public function DBQuery ... public function DBFetchArray ... } class SessionManager{ //or any other object that neeeds a DB connection public function loadDB (Database $db){ //type hint .... } } $session = new SessionManager(); $session->loadDB(mysqliDB::getInstance()); //and so on for any other objects that need a DB Could this be a correct solution? Quote Link to comment Share on other sites More sharing options...
keeB Posted April 11, 2008 Share Posted April 11, 2008 Sure and no First off, __construct() can't return any values so it can't be a singleton. Second, I suggest programming to an interface instead of using a base class. My reasoning is here: http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html Following the rules in that guide you end up with something like this: <?php interface Database { public function connect($host, $username, $password, $database); //establishes and selects database public function query($query); //queries the database, returns array public static function getInstance(); . . . etc } class mySQLi implements Database { private $instance = null; //for singleton public function __construct() {} public static function getInstance() { if ($instance == null) //bla bla } public function connect($...) { mysqli_connect($host, $username, $password) or throw new SQLException("Could not connect to database"); mysqli_select_db($db, $con); } } //now, finally, a DAO. class AlbumDao { private $dbconnection; public function getImageByName($dir) { //find an image in a certain directory; } public function getImageById($id) { //select * from images where id = id } public function initialize($albumName) { // select * from album a // inner join images i on i.album = a.id // inner join videos v on v.album = a.id // where album.short_tile = '$albumName' } public function setDbConnection(Database $dbconnection) {$this->dbconnection = $dbconnection;} } class Album { private $name; private $title; private $dir; private $dao; public function __construct($name) { $this->name = $name; $this->init(); } private init() { $this->dao->initialize($this->name); } public function getImageList() { // some helper functions which return a list of Image objects } public function getVideoList() { // some other helper functions } public function setDao(AlbumDao $dao) {$this->dao = $dao} } //client $db = new mySQLi::getInstance(); $db->connect(...); $album = new Album("Family Photos"); $a->setDao($db); // make sure it's using our database $a->init(); foreach($a->getImageList() as $image) // loop through and get some images.. ?> Quote Link to comment Share on other sites More sharing options...
MelodyMaker Posted April 11, 2008 Author Share Posted April 11, 2008 Yes, you're right. I'm sorry for that, what I was trying to explain is that the constructor is private because I use a singleton pattern to instantiate the object. Sorry, I put a wrong comment there... Anyway, at this point I wonder what are abstract classes useful for. After reading that article about Java and derived classes it seems that abstract classes (and, in general, base classes) should be replaced by interfaces. I'm a bit confused about that... Quote Link to comment Share on other sites More sharing options...
keeB Posted April 12, 2008 Share Posted April 12, 2008 Well, there are times when you really want a base class, and that is when you want common functionality across all (derived) objects. Quote Link to comment Share on other sites More sharing options...
MelodyMaker Posted April 14, 2008 Author Share Posted April 14, 2008 Thank to all of you. Let's suppose that it is NOT a Database object that you want to pass across the pages of,say, a website and use in objects, but anything else (for example a Log or Error object). Is there a way to change only the class (base class) and, of course, his name without changing every instantiation across the script ($newObject = new newObject()...) something like this, I mean: interface BaseObject | Obj1 OBj2 OBj3 .... (all implement the interface and this objects are interchangeable, I could use Obj1 or Obj2, or Obj3...) | Then, a CurrentObject that someway (which?) stores or get the Object I need (Obj1 or Obj2, or Obj3,...) This way, I can keep the scripts untouched because I instantiate the CurrentObject: $newObject = new CurrentObject() // does not matter if this uses Obj1 or Obj2 or Obj3... I don't know if the question is clear, I hope so. Thanks in advance. Davide Quote Link to comment Share on other sites More sharing options...
keeB Posted April 14, 2008 Share Posted April 14, 2008 http://en.wikipedia.org/wiki/Factory_method_pattern Quote Link to comment Share on other sites More sharing options...
MelodyMaker Posted April 14, 2008 Author Share Posted April 14, 2008 http://en.wikipedia.org/wiki/Factory_method_pattern Thanks. This is exactly what I wanted. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.