Database support
| 12 different drivers | MySQL only |
API
| OOP | OOP procedural |
Connection
| Easy | Easy |
Named parameters
| Yes | No |
Object mapping
| Yes | #Yes |
Prepared statements (client side)
| Yes | #No |
#Performance
| Fast | Fast |
Stored procedures
| Yes##Yes |
|
一、連接
##
// PDO$pdo = new PDO("mysql:host=localhost;dbname=database", 'username', 'password');
// mysqli, procedural way$mysqli = mysqli_connect('localhost','username','password','database');
// mysqli, object oriented way$mysqli = new mysqli('localhost','username','password','database');
##二、API 支援
PDO和MySQLi都是透過物件導向的形式提供API,但同時MySQLi也提供了流程導向的API,這種形式對於新手來說更容易理解。如果你對原生的php mysql 驅動熟悉,你會發現很輕鬆得就能使用MySQLi的介面來替換原來的資料存取。用PDO的好處是,PDO支援多種資料庫,而MySQLi只支援MySQL,一但你掌握了就你可以隨心所欲的使用連接多種資料庫。 三、資料庫的支援
PDO比MySQLi最大的優點就是PDO支援很多種資料庫,而MySQLi只支援MySQLi。要看PDO支援哪些資料庫用下面的程式碼:
var_dump(PDO::getAvailableDrivers());
支援多資料庫有什麼好處呢?當你的程式以後想從mysql換成sql server或oracle時,PDO的優勢就能體現出來了,因為換資料庫對於程式介面是透明的,php程式碼改動很小,如果你是用MySQLi,那麼所有用到資料庫的地方都要重寫,這樣的改動我也只能呵呵了。
四、命名參數支援PDO命名參數及參數綁定:
$params = array(':username' => 'test', ':email' => $mail, ':last_login' => time() - 3600);
$pdo->prepare('
SELECT * FROM users
WHERE username = :username
AND email = :email
AND last_login > :last_login');
$pdo->execute($params);
而MySQLi的參數綁定:
##
$query = $mysqli->prepare('
SELECT * FROM users
WHERE username = ?
AND email = ?
AND last_login > ?');
$query->bind_param('sss', 'test', $mail, time() - 3600);$query->execute();
我們從上面比較可以看出PDO是透過命名參數進行值的綁定,而MySQLi的參數綁定是透過點位符「?」並嚴格地依照這個問號的順序來綁定值。這樣雖然程式碼顯得沒有PDO那種透過名字對應那麼長,但是有一個不好的地方是可讀性和可維護性都降低了,參數個數比較少的時候還不覺得,當參數上了10多個或更多的情況就比較痛苦了,你必須要按問號的順序來一個一個對應來賦值,萬一其中一個位錯了,後面的都跟著錯了。 不幸的是MySQLi不支援PDO那樣的命名參數綁定。 五、物件映射(Object Mapping)
基於資料庫的開發一般都是從資料庫中讀取資料然後把這些資料用一個物件來承載。 PDO和MySQLi都支援物件映射,假設有一個User類別,它有一些屬性對應到資料庫。
class User { public $id; public $first_name; public $last_name;
public function info()
{ return '#'.$this->id.': '.$this->first_name.' '.$this->last_name;
}
}
如果沒有物件映射,我們要讀取資料之後,一個一個欄位的賦值,這是很繁瑣的。
下面請看二者使用物件的程式碼:
#$query = "SELECT id, first_name, last_name FROM users";
// PDO$result = $pdo->query($query);$result->setFetchMode(PDO::FETCH_CLASS, 'User');
while ($user = $result->fetch()) { echo $user->info()."\n";
}// MySQLI, procedural wayif ($result = mysqli_query($mysqli, $query)) { while ($user = mysqli_fetch_object($result, 'User')) { echo $user->info()."\n";
}
}// MySQLi, object oriented wayif ($result = $mysqli->query($query)) { while ($user = $result->fetch_object('User')) { echo $user->info()."\n";
}
}
六、安全性
二者都可以防止sql注入。我們先來看一個例子。
$_GET['username'] = "'; DELETE FROM users; /*"
當使用者輸入的username參數的值為上面的值("'; DELETE FROM users; /*"),如果你沒有對這個值做任何處理,使用者就成功將delete語句注入,那麼user表的記錄就會被全部刪除。 6.1、手動轉義
#
// PDO, "manual" escaping$username = PDO::quote($_GET['username']);
$pdo->query("SELECT * FROM users WHERE username = $username");
// mysqli, "manual" escaping$username = mysqli_real_escape_string($_GET['username']);
$mysqli->query("SELECT * FROM users WHERE username = '$username'");
######上面採用了PDO和MySQLi的API自帶的函數對所獲得的參數的值進行了轉義。 ######6.2、prepared statement參數綁定######下面推薦更有效率安全的prepared statement參數綁定的方式:################# ##########// PDO, prepared statement$pdo->prepare('SELECT * FROM users WHERE username = :username');$pdo->execute(array(':username' => $_GET['username']));
// mysqli, prepared statements$query = $mysqli->prepare('SELECT * FROM users WHERE username = ?');$query->bind_param('s', $_GET['username']);$query->execute();
###############七、效能
由於PDO能夠支援其它非MySQL的資料庫,而MySQLi專門針對MySQL設計的,所以MySQLi相對於PDO效能稍微好一些。但是PDO和MySQLi都還是沒有PHP原生的MySQL擴充快。但這樣效能比較其實意義不太大,因為它們都是相當快了,如果你的程式效能要求不是特別苛刻話,三者都可以滿足你。至於你要選擇哪一種就要你根據的實踐情況來權衡。
八、總結
PDO支援12種資料庫驅動和命名參數綁定是其最大優點,透過上面的對比,我相信你也知道了你在自己的專案中會使用哪一種連接資料庫了?
相關建議:
001 - PDO 用法詳細解析