Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

So I'm designing a reporting system at work it's my first project written OOP and I'm stuck on the design choice for the DB class.
Obviously I only want to create one instance of the DB class per-session/user and then pass it to each of the classes that need it. What I don't know it what's best practice for implementing this. Currently I have code like the following:-

class db
{
    private $user = 'USER';
    private $pass = 'PASS';
    private $tables = array( 'user','report', 'etc...');

    function __construct(){
        //SET UP CONNECTION AND TABLES
    }
};

class report{
function __construct ($params = array(), $db, $user)
 {        
    //Error checking/handling trimed
    //$db is the database object we created
    $this->db = $db;

    //$this->user is the user object for the logged in user
    $this->user = $user;

    $this->reportCreate();
 }

public function setPermission($permissionId = 1)
{
    //Note the $this->db is this the best practise solution?
   $this->db->permission->find($permissionId)

    //Note the $this->user is this the best practise solution?        
    $this->user->checkPermission(1)

    $data=array();
    $this->db->reportpermission->insert($data)
}
};//end report

I've been reading about using static classes and have just come across Singletons (though these appear to be passé already?) so what's current best practice for doing this?

share|improve this question
1  
Related (on Stack Overflow): Who needs singletons? –  Yannis Rizos Oct 25 '12 at 5:17

2 Answers 2

up vote 5 down vote accepted

Singletons in PHP are quite useless, your instances are created when the script is executed, and die when the script ends, regardless of whether they are singletons or not. This is by design, PHP follows a share nothing architecture.

Just continue doing what you already do, it even has a fancy name: constructor injection. Read up on dependency injection, and if you want to make your constructor a bit more robust, consider type hinting:

class report {
    function __construct (array $params = array(), db $db, $user)
    {        
        ....
    }

    ...
}

Further reading:

share|improve this answer
    
Okay, thanks! Looks like I had thought out the best solution already. For anyone coming across this question this link:- http://fabien.potencier.org/article/11/what-is-dependency-injection Explains it nice and quickly (plus uses a big which is nice) –  Stephen Oct 25 '12 at 6:33
    
@Stephen Yes, that's a great blog post. Also note that Fabien is the creator of Symfony, one of the most popular php frameworks, and Pimple, a small, easy, and straightforward DI container (if you ever need one). –  Yannis Rizos Oct 25 '12 at 17:08
    
@Stephen I've added a few related questions on singletons, di and constructor injection. Since DI is a new concept for you, keep in mind that it's not a panacea, it can be abused as any other concept in OO design. –  Yannis Rizos Oct 25 '12 at 23:51

I see what Yannis Rizos is saying, but it's not valid in the context of implementing a design pattern in PHP. Yes, they are short lived which i will admit does limit the use of "some" patterns but that non the less stops you from implementing them, after all, they are "concepts" done using an Object Oriented Paradigm.

The singleton (and others such as factory) ARE usefull in PHP just like any other language. Singleton is in fact one of the more used out of the many patterns and is just as useful in PHP as in any other language which is what confused me about Yannis Rizos response. So for your own sake, i would ignore his ignorance in understanding the use and purpose of design patterns especially in PHP as it will further confuse you.

A singleton simply means you can only ever create ONE instance of the class and that is it. It has all the usual benefits of the design pattern the same as in any other language (including both those that run for a fraction of a second or for days on end - even PHP scripts can be daemonised and then they can run for days as well).

You can implement it like this (notice the private constructor, VERY important in preventing multiple instances and also notice the static keyword used throughout):

class db {

    private static $connection = null;

    /**
    * private so it can ONLY be instantiated from within itself and never created outside of the class - this gives you the control you need
    */
    private function __construct(){
        self::$connection = 'connected'; //replace with the actuall connection to the db code
    }

    /**
    * connects to db and creates instance
    */
    public static function get_instance() {

        if (self::$connection === null) {
            return new self();
        }

        return self::$connection;

    }

    /**
    * access the connection
    */
    public function query($query) {
        return mysql_query($query, self::$connection);
    }

    public function __clone() {
        trigger_error('Can not be cloned.', E_USER_ERROR);
    }

    public function __wakeup() {
        trigger_error('Can not be deserialized.', E_USER_ERROR);
    }

}

//first time used, so will create a NEW connection to the db and store it
$db = db::get_instance();
$db->query("SQL QUERY HERE");

//will NOT create a new connection, but instead use the existing one - this is the singleton pattern because you can only use a SINGLE INSTANCE of the object.
$another_connection = db::get_instance();
$db->query("fdsfdsfsd");
share|improve this answer
1  
So your arguments for singletons is that it's an oft used design pattern? Lots of developers using something doesn't make it a good choice, and, since you appear to have a rather misguided approach to object oriented design, dependency injection is one of the SOLID principles, and constructor injection is a design pattern (however simple it might seem). Furthermore, if you are going to use words like "ignorance", at least try to write a proper singleton, your example class is cloneable (thus, not a singleton). –  Yannis Rizos Oct 25 '12 at 23:26
    
Oh, yeah your "half" right, since YOU also forgot that it's not just ONE (clone) i forgot, but you also forgot deserializing it as well. So it appears you also forgot one. Thanks tho, forgot about those "two" which i have now added. P.S. The PHP documentation also does it VERY similar to the example i showed, so if you have an issue with it, bring it up with the coders who contribute to the PHP Documentation, not me :p –  VBAssassin Oct 26 '12 at 0:07
1  
Argh, you're still doing it wrong. If you don't want your object to be serializable, you should trigger an error on __sleep(). __wakeup() is called on deserialization, why let your object get serialized in the first place (serialization is an expensive operation)? Also: trigger_error()? In 2012? On an answer that supposedly advocates "Object Oriented Paradigm"? Are you kidding me? (hint: exceptions) –  Yannis Rizos Oct 26 '12 at 0:18
    
Haha, it's getting early man, give me a break lol. But for the record, yes, it would be better not letting it get serialized in the first place and changing trigger error probably would be better replaced with throw new Exception. Anyway, your getting anal about me just making a point of showing him which is more than what you did. If you wanted to get really picky, the connection to the database doesn't work, the query method fails and it uses mysql instead of mysqli... bla bla bla. Point is, it shows how a singleton "works" minus the few tidy up tweaks. Leave my answer alone now! –  VBAssassin Oct 26 '12 at 0:50
    
Heh, I am fooling around a bit, true. However, you really need to research singleton a bit more thoroughly (see the references in my answer), it's an anti-pattern. It can be convenient, but global state is just bad form, it severely hurts testability. –  Yannis Rizos Oct 26 '12 at 0:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.