Q:什么是PDO
A:pdo-php data object 是一个数据库访问层,提供统一的方法去访问多种数据库。
连接msql数据库
通过mysql_*方法可以说是老方法(已经在5.5之后被废除了)
$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);
通过PDO:你只需要就是创建一个PDO对象。构造函数接受参数去指定数据库源,构造方法通常接受4个参数:DSN(data souse name),用户名、密码。
恐怕除了DSN之外你都很熟悉,这是PDO的新特性。DSN可以说就是一个选项构成的字符串,这些字符串告诉PDO应该用哪些驱动,还有一些连接的细则。更多的请查看官方文档。
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
提示:你也可是使用charset=UTF-8,但有时候可能出现无法解释的问题,所以更好使用utf8
如果说有任何的连接错误,都会抛出一个PDOException 对象,你可以捕获他去进一步处理。
译者注:后续会翻译PDOException 相关。
你也可以传递多个驱动选项(以数组的形式)作为第四个参数。我建议传递一些可以把pdo置为异常模式的参数。因为一些pdo驱动不支持一些本地预处理语句,所以pdo会执行模拟的预处理。这也允许你手动的开启这个模拟方式。如果要使用本地服务端的预处理语句,你应该显示的把他置为false。
另外你可以在mysql中关闭预处理模拟(prepare emulation),这个在mysql中是默认开启的,但应该为了安全的使用pdo把他关闭。
稍后为我会解释为什么预处理模拟(prepare emulation)应该被关闭。
只有在使用旧版本的的mysql才有用,这也是我不推荐的。
一下是一个可以用的例子:
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8',
'username',
'password',
array(PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
可以稍后在设置属性吗?
可以,请使用setAttribute 方法。
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8',
'username',
'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
错误处理
PDO比mysql在错误处理上更简单。
在mysql_*中经常使用的是:
//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));
OR die()并不是一个很好的处理错误的方法,因为die之后我们啥也不能做。只会让脚本中断,然后输出错误信息,这是你万万不想让你的末端用户知道的,会让黑客知道你的结构。有一个解决方案,mysql_*的返回值可以与mysql_error() 结合起来去处理错误。
PDO提供了一个更好的解决方案:异常。任何我们进行的PDO操作都应该防盗try-catch里面。我们可以强制pdo加到三个错误模式:
- PDO::ERRMODE_SILENT. 只是设置错误代码,跟mysql_*的方法差不多,你可以查看结果,通过$db->errorInfo() 去获取错误详情。
- PDO::ERRMODE_WARNING
- PDO::ERRMODE_EXCEPTION 抛出异常,代表了pdo产生的一个错误,你不应该在你的代码中抛出PDOException 。他的表现很像or die(mysql_error())没有被捕获时候的样子。但又不想ordie()。PDOException 可以被优雅的捕获和处理。
举例:
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
应该把他们包装到try-catch里,像这样:
try {
//Connect as appropriate as above
$db->query('hi'); //Invalid query!
}
catch (PDOException $ex) {
echo "An Error occured!"; //User friendly message/message you want to show to user
some_logging_function($ex->getMessage());
}
你现在不应该处理try-catch,更有意义的是像这样:
function data_fun($db) {
$stmt = $db->query("SELECT * FROM table");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
//Then later
try {
data_fun($db);
}
catch(PDOException $ex) {
//Here you can handle error and show message/perform action you want.
}
下一章我们会介绍增删改查