PHP - 如何从其他(多个)类访问pdo对象 [英] PHP - How to access pdo object from other (multiple) classes

查看:137
本文介绍了PHP - 如何从其他(多个)类访问pdo对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am switching my MVC to use PDO (I know, overdue). My application has, in the past, used the following class hierarchy:

Database.class> Main.class> User.class

Database.class>Main.class>User.class

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

(each one extending the other). But before any object is created, the mysql connection was made (mysql_connect). Once the connection was open I could use Database.class as a wrapper class through which all my queries were performed. Through extention, a query in the User.class could be made simply by calling the "query" function ($this->query).

使用PDO试图模仿过程但发现错误。我在Database.class中创建了一个singleton函数:

Using PDO, I've tried to imitate the process but find errors. I created a singleton function in the 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;
}

然后在Main.class中获取实例:

Then in Main.class I get the instance:

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

所以在User.class中,我尝试调用

So in User.class I try to call

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

所以我可以从Main.class对象中运行任何查询。但是如果我尝试从User.class对象运行查询,我得到错误:调用成员函数query()on一个非对象换句话说,如果User.class扩展主我应该能够访问变量$ db in Main from User.class(当创建User对象时,我调用Main的构造函数)。部分的问题是Main.class在应用程序中创建,因为它是自己的对象,我相信导致PDO的两个实例被创建 - 这就是为什么它不工作通过扩展(通过第二个对象,也扩展database.class)

So I can run any queries fine from the Main.class object. 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). 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实例),并传递pdo对象到构造函数?我宁愿不必这样做(更少的标记越好)所以另一个选择是使用一个STATIC变量,所有类使用?什么是最好的方法? (让我知道如果这是混乱)

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? 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? What's the best method? (let me know if this is confusing)

我看到人们使用注入为此,我已经看到了扩展pdo包装类的例子(但只有一次)。

I've seen people using injection for this, and I've seen examples of extending the pdo wrapper class (but only once).

谢谢! (我爱堆栈溢出!)

Thanks! (I love stack overflow!)

推荐答案

你不想要任何扩展数据库类,单例,你只能有一个实例...你想让他们使用数据库类。所以你会把最抽象的数据库方法放在 Database 上,然后为特定的事情创建查询的方法将在 User 或你有什么。这意味着您的数据库实际上包装 PDO ,这是所有其他类用于数据库操作。可能甚至不需要 Main Base 类,除非您试图实现活动记录或某事。

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. This means your Database actually wraps PDO and is what all other classes work with for db operations. The Main or Base class may not even be needed unless you are trying to implement active record or something.

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
       }
    }

这篇关于PHP - 如何从其他(多个)类访问pdo对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆