PDO和MySQLi区别与选择?

当用PHP访问数据库时,除了PHP自带的数据库驱动,咱们通常还有两种比较好的选择:PDO和MySQLi。在实际开发过程当中要决定选择哪种首先要对两者有一个比较全面的了解。本文就针对他们的不一样点进行分析,并对多数据库类型支持、稳定性、性能等等方面进行对比。php

 

 
PDO MySQLi
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

 

 

1、链接

// 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');

2、API 支持

PDO和MySQLi都是经过面向对象的形式提供API,可是同时MySQLi也提供了面向过程的API,这种形式对于新手来讲更容易理解。若是你对原生的php mysql 驱动熟悉,你会发现很轻松得就能使用MySQLi的接口来替换原来的数据访问。用PDO的好处是,PDO支持多种数据库,而MySQLi只支持MySQL,一但你掌握了就你能够为所欲为的使用链接多种数据库。html

3、数据库的支持

PDO比MySQLi最大的优势就是PDO支持不少种数据库,而MySQLi只支持MySQLi。要看PDO支持哪些数据库用下面的代码:mysql

var_dump(PDO::getAvailableDrivers());

支持多数据库有什么好处呢?当你的程序之后想从mysql换成sql server或者oracle时,PDO的优点就能体现出来了,由于换数据库对于程序接口是透明的,php代码改动很小,若是你是用MySQLi,那么全部用到数据库的地方都要重写,这样的改动我也只能呵呵了。sql

4、命名参数支持

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的参数绑定:api

$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那样的命名参数绑定。oracle

5、对象映射(Object Mapping)

基于数据库的开发通常都是从数据库中读取数据而后把这些数据用一个对象来承载。PDO和MySQLi都支持对象映射,假设有一个User类,它有一些属性对应到数据库。app

class User {
    public $id;
    public $first_name;
    public $last_name;
     
    public function info()
    {
        return '#'.$this->id.': '.$this->first_name.' '.$this->last_name;
    }
}

若是没有对象映射,咱们要读取数据以后,一个一个字段的赋值,这是很繁琐的。ide

下面请看两者使用对象的代码:

$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 way
if ($result = mysqli_query($mysqli, $query)) {
    while ($user = mysqli_fetch_object($result, 'User')) {
        echo $user->info()."\n";
    }
}
// MySQLi, object oriented way
if ($result = $mysqli->query($query)) {
    while ($user = $result->fetch_object('User')) {
        echo $user->info()."\n";
    }
}

6、安全性

两者均可以防止sql注入。咱们先看一个例子。

$_GET['username'] = "'; DELETE FROM users; /*"

当用户输入的username参数的值为上面的值("'; DELETE FROM users; /*"),若是你没有对这个值作任何处理,用户就成功将delete语句注入,那么user表的记录就会被所有删除。

6.一、手动转义

// 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.二、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();

7、性能

因为PDO可以支持其它非MySQL的数据库,而MySQLi专门针对MySQL设计的,因此MySQLi相对于PDO性能稍微好一些。可是PDO和MySQLi都仍是没有PHP原生的MySQL扩展快。可是这样性能比较其实意义不太大,由于它们都是至关快了,若是你的程序性能要求不是特别苛刻话,三者均可以知足你。至于你要选择哪种就要你根据的实践状况进行权衡。

8、总结

PDO支持12种数据库驱动和命名参数绑定是其最大优势,经过上面的对比,我相信你也知道了你在本身的项目中会使用哪种链接数据库了?

相关文章
相关标签/搜索