1
   function __construct($name, $lastName, $address, $rollNo)
    {
           $this->name = $name;
           $this->lastName = $lastName;
           $this->address = $address;
           $this->rollNo = $rollNo;

           $this->conn = new \PDO('mysql:host=localhost;dbname=students', 'root', '');
    }

    public function getUser($id){
        $sql = "SELECT * FROM students WHERE id = ".intval($id);

        foreach($this->conn->query($sql) as $row){
            $user['name'] = $row['name'];
            $user['address'] = $row['address'];
            $user['roll_no'] = $row['roll_no'];  
        }
        return $user;

    }

So what i am trying to learn is how i can use a single PDO object in my all classes rather than creating $conn in all classes like users, courses etc.

I've came across the words Dependency Injection , Singleton , Factory and for me as a beginner these are all mixed up.

Also i want to know is it a bad practice what i am doing in my code for creating new objects for PDO.

Raheel
  • 8,716
  • 9
  • 60
  • 102
  • 1
    (+1) Your question is valid one. Those wors togheter with others, are known as "Best Programming Practices", are ways to do better a program, yet I totally agree, that are difficult to understand and to use. – umlcat Nov 21 '14 at 18:11
  • 1
    possible duplicate of [Design Patterns: How to create database object/connection only when needed?](http://stackoverflow.com/questions/16472924/design-patterns-how-to-create-database-object-connection-only-when-needed) – Jimbo Nov 28 '14 at 13:54

3 Answers3

2

A singleton is a control class that will ensure only one instance of a given object will exist at a time. So instead of calling $conn = new PDO() in every object, creating multiple instances of PDO(), you can write a singleton class named Database and use $conn = Database::instance() instead.

class Database
{
    static $instance = null;
    static function instance()
    {
        if (self::$instance == null)
            self::$instance = new PDO('mysql:host=localhost;dbname=students', 'root', '');
        return self::$instance;
    }
}

Basically what it does is create a PDO() class if it doesn't exist, and reuse it if it was already instanced before.

As a side advantage, you also won't need to have your database credentials spread all over the project. The class Database will have it and noone else.

Havenard
  • 27,022
  • 5
  • 36
  • 62
  • 2
    This is one solution. But i remember I've read somewhere that we should use Dependency Injection in these type of cases rather than singelton. I don't actually know Dependency Injection and the Singleton is perfect for my scenario. But would like to know your opinion – Raheel Nov 21 '14 at 21:18
  • @RaheelKhan It would be like, making a class that you can instance, this class will behave just like the `PDO` class, but its actually a "man in the middle", providing an indirect interfacing with the actual `PDO` class that is instanced using the singleton method. It envolves using PHP magic methods like `__call()` etc. But for this particular case, it would be just bling. It would only make sense when you are improving the functionality of the original class, like this: https://gist.github.com/Havenard/cc0dec6f61380855367c – Havenard Nov 22 '14 at 01:07
  • This class allows queries with prepared statement in a single command, like `Database::QueryRow('SELECT * FROM users WHERE id = ?', 'i', 12345, true)`, will return an associative array with the requested data or `false` on error, with no need to go through all the database interacting process. – Havenard Nov 22 '14 at 01:12
  • 1
    Singletons have no place in the PHP Request/Response lifecycle and are poor practice at best; and coupling monstrosities at worst. [Read this](http://stackoverflow.com/a/4596323/736809). Also, dependency injection is just the posh word for passing an object into another one (thus inverting the control: [link](http://en.wikipedia.org/wiki/Inversion_of_control)). It's done this way for a reason. – Jimbo Nov 28 '14 at 13:57
  • I also missed static calls. Yay! Let's introduce external, hardcoded dependencies and mutable global state with statics! – Jimbo Nov 28 '14 at 14:18
  • 1
    This is not a singleton. It's a bunch of static methods/properties on a class. You could just as well use global variables, it'd be all the same. Also, as @Jimbo said, singletons in PHP don't make any sense. – Florian Margaine Nov 28 '14 at 14:52
0

You could make a class called say 'Database' to deal with connecting to MySQL and setting up the PDO.

so something like...

class Database{
    private $host      = DB_HOST;
    private $user      = DB_USER;
    private $pass      = DB_PASS;
    private $dbname    = DB_NAME;

    private $dbh;
    private $error;

    public function __construct(){
        // setup dsn
        $dns = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
        try{
            $this->dbh = new PDO($dsn, $this->user, $this->pass);
        }
        catch(PDOException $e){
            $this->error = $e->getMessage();
        }
    }

}

And then in your other classes just assign the class to a variable in your other classes so..

$db = new Database();

That would avoid your code duplication. You could also create functions in the Database class to carry out PDO queries as well.

ggilberth
  • 1,128
  • 10
  • 19
  • 2
    I have this one in mind but i personally feel it not good. Is almost the same thing of creating new PDO object for every entity in my project. – Raheel Nov 21 '14 at 21:12
-2

Create a parent class with the connection in it and make a child class that extends the parent class

class Main {

    protected $dbh;

    function dbConnect() {

        $options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);

//DB_HOST, DB_NAME, DB_USER, DB_PASS are set via define() 
//e.g. define("DB_HOST", "localhost");

            $dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME;
            $this->dbh = new PDO($dsn, DB_USER, DB_PASS, $options);

    }

Then..

class User extends Main {

    function crudRead() {
        parent::dbConnect(); //called from the main class
        $db = $this->dbh->prepare('SELECT * FROM user');
        $db->execute();
        return $db->fetchAll(PDO::FETCH_ASSOC);
        }
}
Pwner
  • 791
  • 5
  • 16