【问题标题】:PHP PDO class constructionPHP PDO 类构建
【发布时间】:2012-05-11 15:22:42
【问题描述】:

我对 PDO 和 OOP 都很陌生。我正在尝试编写一个连接到数据库并更新插入和修改它的类。我有几个问题:

  1. 在构造函数中连接数据库是好的做法吗?

  2. 一个类应该更新、插入、修改和连接,还是应该分成几个类?

  3. 为什么 runQuery 不工作?我假设它是因为 $pdo 是在不同的范围内定义的。我怎样才能让它发挥作用?

  4. 如果该类包含在每个页面的顶部,这是否意味着每次加载新页面时它都会重新连接到数据库,这会导致安全问题吗?

对过多的问题表示歉意。提前感谢您的任何回答。

<?php
class Login{

private $_username;
private $_password;
private $_host;
private $_database;
private $_driver;

//Connect to the database

function __construct($configFile){

    $connectionDetails = parse_ini_file($configFile);

    $this->_username = $connectionDetails['username'];
    $this->_password = $connectionDetails['password'];
    $this->_host = $connectionDetails['host'];
    $this->_database = $connectionDetails['database'];
    $this->_driver = $connectionDetails['driver'];

    $pdo = new PDO("$this->_driver:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password);

}

public function loginAllowed($user, $pw){

    $sth = $pdo->setFetchMode(PDO::FETCH_ASSOC);
    print_r($sth);
}

public function runQuery($query, $params){
    $sth = $this->pdo->prepare($query);
    $sth->execute($params); 
}
}

【问题讨论】:

    标签: php class pdo


    【解决方案1】:

    因为$pdo 是构造函数和方法loginAllowed 中的局部变量。您应该将其设为实例变量 (private $pdo),以便您可以通过 $this-&gt;pdo 调用它。我也建议在这里使用type hinting,在构造函数中给PDO类作为参数。

    例子

    <?php
    class Login {
        private $pdo;
        // Your other instance variables
    
        public function __construct(PDO $pdo)
        {
            $this->pdo = $pdo;
        }
    
        // Your other methods
    }
    
    $pdo = new PDO("...");
    $login = new Login($pdo);
    

    你不应该打扰你的班级阅读设置和初始化你的数据库连接(一定要阅读separation of concerns),不要让你的班级出现。只需将 PDO 对象作为参数(我使用了type hinting,这样您就不得不提供PDO 类型的对象)。另一个优点是您现在可以确保只有一个活动的数据库连接(您可以在代码库中管理它),创建多个连接是不必要的,而且绝对不需要(性能方面)。

    还可以使用require_once 来包含您的类定义。否则,您会收到很多关于重新声明的错误(并且您希望避免这种情况)。

    【讨论】:

    • 感谢您的精彩回答,我将您的所有建议付诸实践。我在传递 $pdo 对象时遇到类型提示的小问题(没有它可以正常工作),我收到以下错误:可捕获的致命错误:传递给 Login::__construct() 的参数 1 必须是PDO 的实例,给定字符串 我使用 gettype 来确保传递的变量 im 实际上是一个对象。我很困惑.....
    • 您将字符串作为参数。你要做的是在你的类之外创建一个 PDO 实例,并将这个实例作为参数。 (类型提示非常强大,因为您现在可以将参数强制为一种类型(此时仅是类)。)
    • 我这样做$pdo = new PDO("$driver:host=$host;dbname=$database", $username, $password);(在课堂外)然后这个$login = new Login($pdo);,当我尝试打印我正在传递的变量时($pdo)我得到这个:类的对象PDO 无法转换为字符串
    • 这很奇怪,对我来说它有效。您可以在 pastebin 上添加更多代码并在此处发布吗?否则很难看出问题可能是什么。
    • 我把你的代码清理了一下:pastebin.com/XMUD0Ki6。如果你运行这个脚本,你到底得到了什么错误? (你得到的输出。)
    【解决方案2】:
    1. 连接到您认为最方便的数据库。只需尝试确保只有一个连接。更多连接到同一个数据库是浪费时间和资源。

    2. 您引用的类在 MVC 架构中称为模型。它通常对给定表执行所有操作。我认为使用单个类来满足您的所有需求没有任何问题 - 只要代码可读且可维护。

    3. 它不起作用,因为$pdo 是一个局部变量。在 ctor 中,改为实例化 $this-&gt;pdo

    4. 包含一个类并不等同于实例化它。一个新实例将建立另一个连接。多次包含它只会给你一个多重声明错误:)。请改用require_once。如果您希望在多个文件中使用该实例,我强烈建议您对 Singleton 模式进行快速搜索。使用单例对象将确保您始终只有一个模型对象实例。

    【讨论】:

      【解决方案3】:

      1) 在构造函数中连接数据库是好习惯吗?

      不行,先连接再查询

      if($this->pdo == null) {
      $this->pdo = new PDO("....");
      

      }

      2) 一个类应该更新、插入、修改和连接,还是应该分成几个类? 为类添加方法

      3) 为什么 runQuery 不工作?我假设它是因为 $pdo 是在不同的范围内定义的。我将如何让这个工作? 改用 $this->pdo

      4) 如果类包含在每个页面的顶部,这是否意味着每次加载新页面时它都会重新连接到数据库,这会导致安全问题吗? 使用静态 $pdo 那么 self::$pdo 将是唯一的一个连接器

      if(self::$pdo == null) {
      self::$pdo = new PDO("....");
      

      }

      【讨论】:

        【解决方案4】:

        不要打扰所有随机的东西,只需在你的构造中替换这个:

        $pdo = new PDO("$this->_driver:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password);
        

        $this->pdo = new PDO("$this->_driver:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password);
        

        并从现在开始将其引用为 $this->pdo。就这么简单!!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-08
          • 1970-01-01
          • 1970-01-01
          • 2012-12-16
          • 2013-07-23
          • 1970-01-01
          • 1970-01-01
          • 2020-01-15
          相关资源
          最近更新 更多