我是PDO的新手。我看了好几个视频。我想像以前一样使用我自己的数据库类。我想使用PDO而不是mysql *函数。我知道在PHP 5.5中不推荐使用mysql *函数
我没有处理我的旧数据库类。因为对新手来说会更难。现在我只创建一个连接。我想选择我的产品。
这是我的代码:
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]:无错误:未在/var/www/dt/includes/class/class.database.php中调用PDO构造函数 第52行
致命错误:在非对象中调用成员函数fetch() 第53行的/var/www/dt/includes/class/class.database.php
我的错误是什么?我该怎么办?
答案 0 :(得分: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异常将自动冒出,您将能够在任何需要的地方处理异常。 E.g:
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
个实例,而且您通常无法做任何事情,所以给它们是有意义的特殊待遇。
答案 1 :(得分: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');