標籤:style blog http io color ar os sp 資料
PHP-MySQL是PHP操作MySQL資料庫最原始的Extension ,PHP-MySQLi的i代表Improvement ,提供了更加進階的功能,就Extension而言,本身也增加了安全性。而PDO(PHP Data Object) 則是提供了一個 Abstraction Layer來操作資料庫。我們通過代碼來初步比較它們之間的差異。
先來看一段PHP-MySQL的通用代碼:
<?php mysql_connect($db_host, $db_user, $db_password); mysql_select_db($dn_name); $result = mysql_query("SELECT `name` FROM `users` WHERE `location` = ‘$location‘"); while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { echo $row[‘name‘]; } mysql_free_result($result); ?>
這種方式的問題是不能Bind Column,容易被SQL注入(SQL注入後續會有文章講到)。所以後來發展出mysql_escape_string() (注意:5.3.0之後棄用) 以及 mysql_real_escape_string()來解決這個問題。一般就會寫成這樣:
<?php $query = sprintf("SELECT * FROM users WHERE user=‘%s‘ AND password=‘%s‘", mysql_real_escape_string($user), mysql_real_escape_string($password)); mysql_query($query); ?>
在PHP-MySQLi中有了不少改進,除了通過Bind Column來解決上述問題,而且也支援Transaction, Multi Query ,並且同時提供了Object oriented style,範例程式碼如下:
<?php $mysqli = new mysqli($db_host, $db_user, $db_password, $db_name); $sql = "INSERT INTO `users` (id, name, gender, location) VALUES (?, ?, ?, ?)"; $stmt = $mysqli->prepare($sql); $stmt->bind_param(‘dsss‘, $source_id, $source_name, $source_gender, $source_location); $stmt->execute(); $stmt->bind_result($id, $name, $gender, $location); while ($stmt->fetch()) { echo $id . $name . $gender . $location; } $stmt->close(); $mysqli->close(); ?>
可以看出這隻中方式已經把PHP-MySQL的問題解決了,當然用MySQL是沒有問題了,如果有一天我的資料庫換成了oralce,postgresql,那就不好辦了,代碼需要大改。所以就PDO就出來了,它把資料庫的操作抽象出來了,而不需要管底層用的是何種資料庫。範例程式碼如下:
<?php $dsn = "mysql:host=$db_host;dbname=$db_name"; $dbh = new PDO($dsn, $db_user, $db_password); $sql = "SELECT `name`, `location` FROM `users` WHERE `location` = ? , `name` = ?"; $sth = $dbh->prepare($sql); $sth->execute(array($location, $name)); $result = $sth->fetch(PDO::FETCH_OBJ); echo $result->name . $result->location; $dbh = NULL; ?>
這樣做的好處有很多:
1. PDO串連資料庫時通過Connection String(如例子中的"mysql:host=$db_host;dbname=$db_name")來決定串連哪種資料庫。
2. PDO可以通過PDO::setAttribute來設定串連時的參數,像是Persistent Connection, 返回錯誤的方式(Exception, E_WARNING, NULL),甚至是返回類名稱的大小等等。
2. PDO支援Bind Column,除了基本的 Prepare, Execute 以外,也可以Bind單一列,並且知道列類型。
4. PDO 是 Abstraction Layer,所以更換資料庫所需修改的代碼量很少。
當然還有DBI方式,如ActiveRecord 以及 Propel ORM(Object-Relational Mapping)都非常好用。
如ActiveRecord,如果現在要用PHP操作這樣的sql語句:
INSERT INTO `users` (id, name, gender, location) VALUES(1, ‘roga‘, ‘male‘, ‘tpe‘)
PDO的寫法:
<?php $sql = "INSERT INTO `users` (id, name, gender, location) VALUES(?, ?, ?, ?)"; $sth = $dbh->prepare($sql); $sth->execute(array(1, ‘roga‘, ‘male‘, ‘tpe‘)); ?>
ActiveRecord的寫法
<?php $user = new User(); $user->id = 1; $user->name = ‘roga‘; $user->gender = ‘male‘; $user->location = ‘tpe‘; $user->save();?>
後者在寫法上大大降低了對SQL的依賴性!
PHP-MySQL,PHP-MySQLi,PDO的差異