PHP - 如何从其他(多个)类访问 pdo 对象


PHP - How to access pdo object from other (multiple) classes

我正在切换我的MVC以使用PDO(我知道,过期了(。我的应用程序过去使用以下类层次结构:

数据库.class>主.class>用户.class

(每个扩展另一个(。但是在创建任何对象之前,已经建立了mysql连接(mysql_connect(。一旦连接打开,我就可以使用 Database.class 作为包装类,通过它执行所有查询。通过扩展,只需调用"query"函数($this->query(即可在User.class中进行查询。

使用PDO,我试图模仿这个过程,但发现错误。我在数据库中创建了一个单例函数.class:

function __construct()
{
    $this->db = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8', DB_USER, DB_PASSWORD);
    $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
public static function getInstance()
{
    if (!isset(self::$instance)){
        $object = __CLASS__;
        self::$instance = new $object;
    }
    return self::$instance;
}
function query($qry,$params=NULL){
    $qry = $this->db->prepare('SELECT * FROM users WHERE userID = :userID');
    $qry->execute(array(':userID' => 1));
    $results = $qry->fetchAll(PDO::FETCH_ASSOC);
    return $results;
}

然后在 Main 中.class我得到实例:

function __construct()
{
    $this->db = parent::getInstance();
}

所以在用户中.class我尝试调用

function __construct(){
    parent::__construct();
}
function test(){
    return $this->db->query("test");
}

所以我可以从 Main.class 对象很好地运行任何查询。但是,如果我尝试从 User.class 对象运行查询,则会收到错误:"在非对象上调用成员函数 query((" 换句话说,如果用户.class扩展了 main,我应该能够从用户访问 Main 中的变量$db.class(我在创建 User 对象时调用 Main 的构造函数(。部分问题是 Main.class 是在应用程序中较早创建的,因为它是自己的对象,我相信会导致创建两个 PDO 实例 - 这就是为什么它无法通过扩展工作(通过第二个对象也扩展数据库.class(

所以我的问题是:有没有办法做到这一点?或者我最好的选择是对我创建的每个对象使用注入(因为有些脚本包含多个扩展 Main 的对象.class - 每次都尝试创建 PDO 的实例(并将 pdo 对象传递给构造函数?我宁愿不必这样做(标记越少越好(所以另一种选择是使用所有类使用的 STATIC 变量?最好的方法是什么?(如果这令人困惑,请告诉我(

见过有人为此使用注入,并且我见过扩展 pdo 包装器类的示例(但只有一次(。

谢谢!(我喜欢堆栈溢出!

您不希望其中任何一个扩展数据库类,因为这基本上会使它们成为您只能拥有一个实例的单例......你想让他们改用数据库类。因此,您将最抽象的数据库方法放在Database上,然后为特定事物创建查询的方法将在User或您拥有什么。这意味着您的Database实际上包装了PDO,并且是所有其他类用于数据库操作的类。甚至可能不需要MainBase类,除非您尝试实现活动记录或其他内容。

class Database {
   static protected $instance;
   /**
    * @var PDO
    */
   protected $connection;
   protected function __construct($dsn, $user, $pass, $attrs = array()) {
       // create pdo instance and assign to $this->pdo
   }
   public static function getInstance() {
       if(!self::$instance) {
           // get the arguments to the constructor from configuration somewhere
           self::$instance = new self($dsn, $user, $pass);
       }
       return self::$instance;
   }
   // proxy calls to non-existant methods on this class to PDO instance
   public function __call($method, $args) {
       $callable = array($this->pdo, $method);
       if(is_callable($callable)) {
           return call_user_func_array($callable, $args);
       }
   }
}
class Main {
   protected $db;
   public function __construct() {
      $this->db = Database::getInstance();
   }   
}
    class User extends Main{
       public function __construct() {
            parent::__construct();
       }
       public function findById($id) {
           $qry = $this->db->prepare('SELECT * FROM users WHERE userID = :userID');
           $qry->execute(array(':userID' => $id));
           $results = $qry->fetchAll(PDO::FETCH_ASSOC);
           return $results
       }
    }