Home » Php » php – PDO incorporation within class

php – PDO incorporation within class

Posted by: admin July 12, 2020 Leave a comment

Questions:

I’m having some issue understanding this. I’d like to start re-writing some old MySQL function code PDO. The way it was set up, is that an external file containing this line (among other things):

// db.php file   

$DB = new dbConnect(SERVER,DB,USER,PASSWORD,3306);

function my_autoloader($class)
{
    require_once ($_SERVER['DOCUMENT_ROOT']."/includes/".'class.' . $class . '.php' );
}

spl_autoload_register('my_autoloader');

Which would create a connection to my database. This is included at the very top of my pages and would also load all my classes. Now, if I want to create a new connection using PDO, I would do the following:

$conn = new PDO('mysql:host='.SERVER.';dbname='.DB.';charset=utf8',USER, PASSWORD);

However, I cannot have this line of code on a separate file and call PDO from within a class like the following:

require_once 'db.php';
class info
{

    protected $ID;

    public function __construct($id)
    {
        $this->ID = $id; // 
    }

    public function getName()
    {
        $query = "SELECT * FROM job";
        $q = $conn->query($query);
        $data = $q->fetch(PDO::FETCH_ASSOC);
            //do something with $data

    }
}

Does this mean I have to establish a connection in the constructor by means of aggregation like the following?

require_once 'db.php';
class info
{
    protected $ID;
    protected $pdo;

    public function __construct($id)
    {
        $this->ID = $id; // 
        $this->pdo = new PDO('mysql:host='.SERVER.';dbname='.DB.';charset=utf8',USER, PASSWORD);
    }

    public function getName()
    {
        $query = "SELECT * FROM job";
        $q = $this->pdo->query($query);
        $data = $q->fetch(PDO::FETCH_ASSOC);
        // do something
    }
}

Or is there another way of doing this that I’m not aware of. It seems tedious trying to re-write all of my classes to incorporate this.

How to&Answers:

Instead of creating the database connection inside the constructor, it’s better to make it a dependency:

public function __construct(PDO $db, $id)
{
    $this->pdo = $db;
    $this->ID = $id;
}

To use it, you would do:

// $db = new PDO('mysql:host='.SERVER.';dbname='.DB.';charset=utf8',USER, PASSWORD);
$info = new info($db, '123');
echo $info->getName();

The chief advantage of this approach is that you no longer have any configuration stored inside your class. Additionally, you can pass anything that implements PDO as well, enabling unit testing with mocked databases.

Answer:

When creating a connection to a database, you should do so in a singleton class. You only ever want to open one connection to a database. For example:

public class database
{
    static $instance;

    public static function getInstance()
    {
          if($self::$instance == null)
          {
                $self::$instance = new PDO(); // string value here.
          }
          return $instance;
    }
}

Then you can call the database::getInstance() method from anywhere in your class, and you don’t need to keep re-writing your connection code.

PS: I’m aware this singleton isn’t thread safe. I was simply trying to highlight the concept to OP.

Answer:

here’s my first attempt:

class database extends PDO {

        protected static $instance;

        protected function __construct(){}

        public static function getInstance()
        {
            if(empty(self::$instance))
            {
                 $db_info = array(
                                "db_host" => SERVER,
                                "db_port" => PORT,
                                "db_user" => USER,
                                "db_pass" => PASSWORD,
                                "db_name" => DB);

                 self::$instance = new Database("mysql:host=".$db_info['db_host'].';port='.$db_info['db_port'].';dbname='.$db_info['db_name'], $db_info['db_user'], $db_info['db_pass']);

             }
             return self::$instance;
        }
}

class info
{
    protected $ID;
    protected $pdo;

    public function __construct($id)
    {
        $this->ID = $id; // 
        $this->pdo = database::getInstance();
    }

    public function getName()
    {
        $query = "SELECT * FROM job";
        $q = $this->pdo->query($query);
        $data = $q->fetch(PDO::FETCH_ASSOC);
        // do something
    }
}

I’m not entirely sure if this is correct as I have no ways of testing this for the moment. Would this be considered correct?