去年就了解到php中mysql扩展已不被建议使用,换用增强扩展mysqli,按照潮流,去年也用mysqli写了点东西,但是始终没有去了解为什么。前几天想要写个网站,又想到了mysqli,因为mysql扩展要考虑的东西太多。
什么是mysqli扩展
首先,大家应该都写过php连接mysql数据库的代码,是不是这样的:
1 2 3 4 5 6
| <?php $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); if(mysqli_connect_errno()){ return false; } ?>
|
这种最原始的方式,其实是mysql扩展,php的mysql连接一般是有三种扩展可以使用的:mysql,mysqli,pdo。
mysqli中的“i”代表“improvement”,可见它是优于mysql的。
那么mysqli有哪些特性?
- mysqli支持mysql的所有功能
- mysqli具有prepare功能,加快速度和防sql注入的
- mysql的每次连接都会新开进程,而mysqli是共用,初始化速度也会比较快。
- 支持事务
- 其他的一些特性
mysqli的使用
mysqli既支持传统php的过程式,也支持现代的面向对象式(oop),本文只有oop式的。
连接
1 2 3 4 5
| $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if(mysqli_connect_errno()){ return false; }
|
执行语句
(仅prepare,大家都弃用原始直接执行的方式吧,SQL Injection,很麻烦的)
1 2 3 4 5 6
| $sql = "INSERT INTO `users` (id, name, gender) VALUES (?, ?, ?)"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('dss', $id, $name, $gender); $stmt->execute();
|
获得结果
1 2 3 4 5 6
| $stmt->bind_result($id, $name, $gender); while ($stmt->fetch()) { echo $id.$name.$gender; }
|
mysqli事务
1 2 3 4 5 6 7 8 9 10 11 12 13
|
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); $mysqli->autocommit(false);
$mysqli->query("INSERT INTO users(id) VALUES (1)"); $mysqli->rollback();
$mysqli->query("INSERT INTO users(id) VALUES (2)"); $mysqli->commit();
|
关闭连接
(十分重要),用完了就关闭,否则会占内存
1 2
| $stmt->close(); $mysqli->close();
|
自己包装的类
这样每次就不用再写连接之类的代码了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| class MysqliDAO { private $mysqli;
public function MysqliDAO() { $this->connect(); }
private function connect() { $this->mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); if(mysqli_connect_errno()){ return false; } $this->mysqli->set_charset('utf8'); return true; }
public function execute($sql, $params, $param_types) { if($this->mysqli == false){ return -1; } $cnt = count($params); $stmt = $this->mysqli->prepare($sql); if(!$stmt){ return -2; } $a_params = array(); $param_type = ''; for($i = 0; $i < $cnt; $i++){ $param_type .= $param_types[$i]; }
$a_params[] = $param_type; for($i=0; $i<$cnt; $i++){ $a_params[] = $params[$i]; } call_user_func_array(array($stmt, 'bind_param'), $a_params); $stmt->execute(); $affected_rows = $this->mysqli->affected_rows; $stmt->close(); $this->mysqli->close(); return $affected_rows; }
function executeQuery($sql, $params, $param_types) { if($this->mysqli == false){ return -1; } $cnt = count($params); $stmt = $this->mysqli->prepare($sql); if(!$stmt){ return -2; } $a_params = array(); $param_type = ''; for($i = 0; $i < $cnt; $i++){ $param_type .= $param_types[$i]; }
$a_params[] = $param_type; for($i=0; $i<$cnt; $i++){ $a_params[] = $params[$i]; } call_user_func_array(array($stmt, 'bind_param'), $a_params); $stmt->execute(); $a_data = array(); $result = $stmt->get_result(); while($row = $result->fetch_array(MYSQLI_ASSOC)) { array_push($a_data, $row); } $result->free(); $stmt->close(); $this->mysqli->close(); return $a_data; }
public function close() { $this->mysqli->close(); }
}
|
调用方式
1 2 3 4 5
| $sql="SELECT 1 FROM `account` WHERE email= ? LIMIT 1"; $params = array($email); $param_types = 's'; $result = (new MysqliDAO())->executeQuery($sql, $params, $param_types); $count = count($result);
|
更多的参考官方手册(PHP: Overview - Manual )
特性比较
下表比较了PHP中三种主要的MySQL连接方式的功能:(看来官方还是挺推崇mysqli的)
|
PHP的mysqli扩展 |
PDO (使用PDO MySQL驱动和MySQL Native驱动) |
PHP的mysql扩展 |
引入的PHP版本 |
5.0 |
5.0 |
3.0之前 |
PHP5.x是否包含 |
是 |
是 |
是 |
MySQL开发状态 |
活跃 |
在PHP5.3中活跃 |
仅维护 |
在MySQL新项目中的建议使用程度 |
建议 - 首选 |
建议 |
不建议 |
API的字符集支持 |
是 |
是 |
否 |
服务端prepare语句的支持情况 |
是 |
是 |
否 |
客户端prepare语句的支持情况 |
否 |
是 |
否 |
存储过程支持情况 |
是 |
是 |
否 |
多语句执行支持情况 |
是 |
大多数 |
否 |
是否支持所有MySQL4.1以上功能 |
是 |
大多数 |
否 |