简体   繁体   English

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

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

I am switching my MVC to use PDO (I know, overdue). 我将我的MVC切换为使用PDO(我知道,已经过期)。 My application has, in the past, used the following class hierarchy: 过去,我的应用程序使用以下类层次结构:

Database.class>Main.class>User.class 数据库类>主类>用户类

(each one extending the other). (每个扩展另一个)。 But before any object is created, the mysql connection was made (mysql_connect). 但是在创建任何对象之前,已经建立了mysql连接(mysql_connect)。 Once the connection was open I could use Database.class as a wrapper class through which all my queries were performed. 打开连接后,我可以将Database.class用作包装器类,通过它可以执行所有查询。 Through extention, a query in the User.class could be made simply by calling the "query" function ($this->query). 通过扩展,可以简单地通过调用“查询”函数($ this-> query)在User.class中进行查询。

Using PDO, I've tried to imitate the process but find errors. 使用PDO,我试图模仿该过程,但发现错误。 I created a singleton function in the Database.class: 我在Database.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;
}

Then in Main.class I get the instance: 然后在Main.class中获得实例:

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

So in User.class I try to call 因此,在User.class中,我尝试调用

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

So I can run any queries fine from the Main.class object. 因此,我可以从Main.class对象运行任何查询。 But if I try to run queries from User.class object I get the error: "Call to a member function query() on a non-object" In other words, if User.class extends main I should be able to access the variable $db in Main from User.class (I call the constructor for Main when the User object is created). 但是,如果我尝试从User.class对象运行查询,则会收到错误消息:“在非对象上调用成员函数query()”换句话说,如果User.class扩展了main,则我应该能够访问该变量User.class中Main中的$ db(我在创建User对象时调用Main的构造函数)。 Part of the issue is that Main.class is created earlier in the application as it's own object, I believe causing two instances of PDO to be created - which is why it doesn't work through extension (through a second object that also extends the database.class) 问题的一部分是Main.class作为其自己的对象在应用程序中创建的较早,我相信会导致创建两个PDO实例-这就是为什么它无法通过扩展(通过第二个对象扩展了)的原因database.class)

So my question is: is there a way to make this happen? 所以我的问题是:有没有办法做到这一点? Or is my best option to use injection for every object I create (because some scripts incorporate multiple objects that extend Main.class - which try to create an instance of PDO each time) and pass the pdo object to the constructor? 还是对我创建的每个对象使用注入的最佳选择(因为某些脚本包含了多个扩展Main.class的对象-每次尝试创建PDO的实例)并将pdo对象传递给构造函数? I'd rather not have to do that (the less markup the better) So another option would be to use a STATIC variable that all classes use? 我宁愿不必这样做(标记越少越好),那么另一种选择是使用所有类都使用的STATIC变量? What's the best method? 最好的方法是什么? (let me know if this is confusing) (让我知道这是否令人困惑)

I've seen people using injection for this, and I've seen examples of extending the pdo wrapper class (but only once). 我见过有人为此使用注入,也见过扩展pdo包装器类的示例(但只有一次)。

Thanks! 谢谢! (I love stack overflow!) (我喜欢堆栈溢出!)

You dont want any of these to extend the database class because that will essentially make them all singletons of which you can only have one instance... you Want to make them USE the database class instead. 您不希望其中任何一个扩展数据库类,因为从本质上来说,它们将使它们只能拥有一个实例而成为所有单例……您想让它们使用数据库类代替。 So you would put you most abstract db methods on the Database and then methods that create queries for specific things would be on the User or what have you. 因此,您会将最抽象的db方法放在Database ,然后针对特定事物创建查询的方法将放在User或您身上。 This means your Database actually wraps PDO and is what all other classes work with for db operations. 这意味着您的Database实际上包装了PDO并且所有其他类都用于db操作。 The Main or Base class may not even be needed unless you are trying to implement active record or something. 除非您尝试实现活动记录或其他东西,否则甚至可能不需要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
       }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM