PHP and PDO class question

2019-01-25 17:37发布

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)

标签: php class pdo
3条回答
混吃等死
2楼-- · 2019-01-25 17:44

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
  }
}
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-25 17:45

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.

查看更多
爱情/是我丢掉的垃圾
4楼-- · 2019-01-25 17:58

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.

查看更多
登录 后发表回答