鱼喃

听!布鲁布鲁,大鱼又在那叨叨了

php的mysql增强扩展mysqli及使用

去年就了解到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有哪些特性?

  1. mysqli支持mysql的所有功能
  2. mysqli具有prepare功能,加快速度和防sql注入的
  3. mysql的每次连接都会新开进程,而mysqli是共用,初始化速度也会比较快。
  4. 支持事务
  5. 其他的一些特性

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);
    //绑定参数,将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默认是执行一条语句之后就提交(commit),修改数据库
//而只执行不提交是不会修改原始数据的,只会存在于为当前事务开辟的空间里
//手动提交后才会真正有效,类似于打草稿确认无误后誊写
//实际上事务是为了处理原子性的事情(银行转帐),不多说了

$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();//需要mysqlnd支持,默认没有
while($row = $result->fetch_array(MYSQLI_ASSOC)) {
array_push($a_data, $row);
}
$result->free();
$stmt->close();
$this->mysqli-&gt;close();
return $a_data;
}

public function close()
{
$this-&gt;mysqli-&gt;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以上功能 大多数