Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP and PDO class question

Tags:

php

class

pdo

I am very new to OOP styled PHP, and I am trying to implement PDO as well. I found this nice little class online which handles the database connection, however I have no idea how to access it from another class. Here is the code:

  class PDO_DBConnect {
    static $db ;
    private $dbh ;
    private function PDO_DBConnect () {
        $db_type = 'mysql';  //ex) mysql, postgresql, oracle
        $db_name = 'postGal';
        $user = 'user' ;
        $password = 'pass' ;
        $host = 'localhost' ;
        try {
            $dsn = "$db_type:host=$host;dbname=$db_name";
            $this->dbh = new PDO ( $dsn, $user, $password);
            $this->dbh->setAttribute(PDO::ATTR_PERSISTENT, true);
            $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch ( PDOException $e ) {
            print "Error!: " . $e->getMessage () . "\n" ;
            die () ;
        }
    }

    public static function getInstance (  ) {
        if (! isset ( PDO_DBConnect::$db )) {
            PDO_DBConnect::$db = new PDO_DBConnect ( ) ;
        }
        return PDO_DBConnect::$db->dbh;
    }
  }

  $db_handle = PDO_DBConnect::getInstance(); 

    class Person 
  {
    function __construct()
    {
      $STMT = $db_handle->prepare("SELECT title FROM posts WHERE id = ? AND author = ? LIMIT 20");
      $STMT->execute(array('24', 'Michael'));

      while ($result = $STMT->fetchObject()) 
      {
        echo $result->title;
        echo "<br />";
      }  
    }
  }

How can I gain access to the $db_handle variable inside of my Person class? Do i have to instantiate the variable inside of the Person class? If so, does that mean I will always have to call it as $this->db_handle ? I was hoping to avoid that. (I still only have a very basic understanding of variable scope with classes)

like image 613
Eujung Kim Avatar asked Jun 09 '11 18:06

Eujung Kim


3 Answers

There are (at least) three ways to handle this. The most portable, and oft recommended is called "dependency injection", whereby you pass the database handle into your class via its __construct() and store it in a class variable. Requires accessing it with $this->db like you didn't want to have to do.

class Person {
  // Member to hold the db handle
  public $db;

  public function __construct($db_handle) {
    // Assign the handle to a class member variable in the constructor
    $this->db = $db_handle;
  }
  public function otherFunc() {
    $this->db; // do something
  }
}

$person = new Person($db_handle);

Next method would be to instantiate the $db_handle inside the constructor rather than passing it in. This is a little harder to test and debug.

class Person {
   public $db;
   public function __construct() {
      $this->db = PDO_DBConnect::getInstance();
   }
}

Finally, you can call $db_handle as a global whenever you use it in your class. This is perhaps the hardest to read and debug.

class Person {
  public function __construct() {
    global $db_handle;
  }
  public function otherFunc() {
    global $db_handle;
    $db_handle; // do something
  }
}
like image 63
Michael Berkowski Avatar answered Nov 17 '22 21:11

Michael Berkowski


You should use Dependency Injection:

$steve = new Person($db_handle);

And yes, using the syntax you're hoping to avoid is the way to do it. You can always assign the class variable to a local method one by saying $dbh = $this->db_handle; which I believe is marginally faster.

like image 3
Nev Stokes Avatar answered Nov 17 '22 21:11

Nev Stokes


If you really must do database work from inside your Person object (separation of concerns says that this should be taken care of elsewhere), you can either pass it as a constructor argument (based on your usage, it looks like that may be the way you want to go), or as a setter injection. For the former:

class Person
{
    function __construct($db_handle)
    {
        // ... your existing code

Then you instantiate your person object like so:

$person = new Person($db_handle);

That's really the only way you can avoid needing to use $this->db_handler without copying the variable into local scope.

like image 3
Derek Stobbe Avatar answered Nov 17 '22 22:11

Derek Stobbe