PHP-MySQL,PHP-MySQLi,PDO的差异

  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的依赖性!

原文地址:https://www.cnblogs.com/zhutianpeng/p/4075101.html