0

我是 PDO 的新手。我看了几个视频。我想像以前一样使用我自己的数据库类。我想使用 PDO 而不是 mysql* 函数。我知道 mysql* 函数在 PHP 5.5 中已弃用

我不在处理我的旧数据库类。因为新手会更难。现在我只创建一个连接。我想选择我的产品。

这是我的代码:

class Database extends PDO {
    private $_server         = "localhost";
    private $_user           = "root";
    private $_password       = "";
    private $_db             = "demo";

    private $_engine = 'mysql';
    private $link = NULL;


    public function __construct() {
        $dsn = $this->_engine.':dbname='.$this->_db.';host='.$this->_server.';charset=utf8';

        try {
            $this->link = new PDO($dsn, $this->_user, $this->_password);
            $this->link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            echo 'Connection failed: ' . $e->getMessage();
        }
    }
}

header('Content-Type: text/html; charset=utf-8');
$DB = new Database();

$sql = "SELECT * FROM product";
$q  = $DB->query($sql);
while($r = $q->fetch(Database::FETCH_ASSOC)){
    $products[] = $r;
}

echo "<pre>";
print_r($products);
echo "</pre>";

我无法取回我的产品。我收到错误。

警告:PDO::query(): SQLSTATE[00000]: No error: PDO 构造函数未在 /var/www/dt/includes/class/class.database.php 第 52 行调用

致命错误:在第 53 行的 /var/www/dt/includes/class/class.database.php 中的非对象上调用成员函数 fetch()

我的错误是什么?我该怎么办?

4

2 回答 2

3

关于您的代码的一些随机想法。

滥用类继承

class Database extends PDO {
    private $link = NULL;

    public function __construct() {
            $this->link = new PDO($dsn, $this->_user, $this->_password);

Database实例本身将是一个对象PDO,因此在另一个 PDO 对象中包含一个 PDO 对象没有任何意义(其外部甚至无法正常工作,因为它尚未初始化)。你只需要这样:

class Database extends PDO {
    public function __construct() {
        parent::__construct($dsn, $this->_user, $this->_password);

未初始化的属性

public function __construct() {
    $dsn = $this->_engine.':dbname='.$this->_db.';host='.$this->_server.';charset=utf8';

所有这些$this->变量来自哪里?您可能希望将它们作为构造函数参数传递。

中断错误处理

try {
    $this->link = new PDO($dsn, $this->_user, $this->_password);
    $this->link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

您的类将连接错误降级为标准输出上的纯字符串。现在,没有办法记录或检测连接错误。

编辑:您询问如何检测或记录您班级的连接错误。你可以做很多事情,但最简单的方法是……什么都不做。严重地。如果您只是从构造函数中删除 try/block,PDO 异常将自动冒泡,您将能够在任何需要的地方处理异常。例如:

try{
    $DB = new Database();
}catch(PDOException $e){
    // I want to handle connection errors in a special way
    // I'll log them here and I'll redirect the user to a static error page
    // That's something I couldn't do from the class constructor because I'd be missing context
}

... 甚至:

try{
    $DB = new Database();
    $sql = "SELECT * FROM product";
    $q  = $DB->query($sql);
    while($r = $q->fetch(Database::FETCH_ASSOC)){
        $products[] = $r;
    }
}catch(Exception $e){
    // I prefer to handle all exceptions the same way, no matter the source
}

...但我会采用第一种方法:连接错误是PDOException您可以期望在生产中找到的唯一实例,而且您通常无能为力,因此对它们进行特殊处理是有意义的。

于 2013-07-30T11:51:31.273 回答
1

首先对您的错误报告进行排序。如果要调试,您需要能够看到错误!

为此,您需要编辑以下设置php.ini

error_reporting display_errors

确保这是在php.ini文件中完成的(而不是ini_set()在代码中使用),然后重新启动服务器。

关于您的database abstraction,我看不到扩展PDO课程的任何真正好处。通常,如果我想重载父级中的某些功能,我只会扩展该类。

可能更有用的是通过将实例包装在您自己的自定义类中encapsulate来对实例的所有调用。PDO这里的主要好处是没有直接处理 PDO 实例的客户端代码,您可以更改或替换类的实现而不影响其余代码。

一个人为的例子:

class Database
{
  protected $config = array();

  protected $pdo;

  public function __construct(array $config)
  {
    $this->config = $config;
  }

  protected function getPdo()
  {
    if (null == $this->pdo) {
      try {
        $config = $this->config;

        $dsn = $config['engine'].':dbname='.$config['database'].';host='.$config['host'].';charset=utf8';

        $this->pdo = new PDO($dsn, $config['user'], $config['password']);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

      } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
      }
    }
    return $this->pdo;
  }

  public function query($sql)
  {
    return $this->getPdo()->query($sql);
  }

}

$db = new Database(array(
  'engine' => 'mysql',
  'database' => 'databasename',
  'host' => 'localhost',
  'user' => 'fred',
  'password' => 'mypassword'
));
$results = $db->query('SELECT * FROM sometable');
于 2013-07-30T11:59:25.990 回答