采用PDO对象和MySQL进行交互

2015-05-18

最近开始自己着手写一个小的项目,采用PHP+MySQL那一套进行编写。所以说,项目一开始便是连接数据库。之前我只了解过通过mysql_connect函数进行连接,这绝对是最低档次的连接数据库,之后知道了一个PDO对象这么个专门处理和数据库之间操作的对象,简直就和发现了新大陆一样。

创建PDO对象

创建PDO对象一般需要三个参数,第一个参数则是要连接数据库的基本信息,包括数据库的IP地址和数据库的名称,第二个参数则是进入数据库的用户名,第三个就是进入密码。

1
2
3
4
5
6
$dbn = "mysql:host=" . DB_HOST . ";charset=utf8;dbname=" . DB_NAME;
try {
$db = new PDO($dbn, DB_USER, DB_PASS);
} catch (Exception $e) {
die($e->getMessage());
}

SQL语句准备

这里以event表为例,以下为表的结构

1
2
3
4
5
6
7
8
9
+-------------+-------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------------------+----------------+
| event_id | int(11) | NO | PRI | NULL | auto_increment |
| event_title | varchar(80) | YES | | NULL | |
| event_desc | text | YES | | NULL | |
| event_start | timestamp | NO | MUL | 0000-00-00 00:00:00 | |
| event_end | timestamp | NO | | 0000-00-00 00:00:00 | |
+-------------+-------------+------+-----+---------------------+----------------+

若SQL中带有php中的参数,一种可以直接在以{$param}的形式将值传进去,但是这样类型不好控制,还有一种弊病就是容易被SQL注入。所以还有一种则是采用PDO对象附带的参数绑定函数,这样那么对应的SQL语句就需要占位符,好处就是可以在一定程度上避免被sql注入,还可以使用预处理语句,这样运行的效率更高。占位符大致可分为以下两类。

1、命名参数

需自定义一个字符串作为“命名参数”,每个参数前需要冒号开始

1
$sql = "select * from event where `event_id`=:id and `event_title`=:title";

2、问号参数

问号参数一定要和字段的位置顺序对应。

1
$sql = "select * from event where `event_id`=? and `event_title`=?";

交互操作

前期的准备都已经OK了,那么接下来就开始和数据库进行交互了

1、准备语句

使用prepare()函数准备预处理语句,该函数返回PDO对象。当重复执行一个sql查询,只是参数不一样的时候,这时候使用预处理效力最高,上面写的两种sql语句准备都是在做预处理,占位符的作用就是用来空出参数的位置。

1
$stmt = $db->prepare($sql);

参数绑定一种可以用到bindParam()函数,具体函数的句法如下

boolean PDOStatement::bindParam(mixed parameter,mixed &variable[,int datatype[,int length[,mixed driver_options]]]);

上代码

1
2
$stmt->bindParam(":id", $id, PDO::PARAM_INT);
$stmt->bindParam(":title", $title, PDO::PARAM_STR);
1
2
$stmt->bindParam(1, $id, PDO::PARAM_INT);
$stmt->bindParam(2, $title, PDO::PARAM_STR);

还有一种参数绑定的形式则是直接在execute函数里面添加参数列表,详细见下

3、执行

execute([array])方法负责执行准备好的查询,需要替换占位符。一种则是用bindParam函数替换,还有一种则是直接在execute函数中输入array表示。

4、获取数据

如果执行的是查询语句的话,就得获取从数据库中查询的数据。下面两个函数是我比较常用的。

这两个函数的参数基本相同,下面一一介绍。

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
array(3) {
[0]=>
array(5) {
["event_id"]=>
string(1) "1"
["event_title"]=>
string(14) "New Year's Day"
["event_desc"]=>
string(14) "Happy New Year"
["event_start"]=>
string(19) "2015-01-01 00:00:00"
["event_end"]=>
string(19) "2015-01-01 23:59:59"
}
[1]=>
array(5) {
["event_id"]=>
string(1) "3"
["event_title"]=>
string(19) "Middle of the Mouth"
["event_desc"]=>
string(25) "The Middle of the January"
["event_start"]=>
string(19) "2015-01-16 00:00:00"
["event_end"]=>
string(19) "2015-01-16 23:59:59"
}
}
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
array(3) {
[0]=>
array(10) {
["event_id"]=>
string(1) "1"
[0]=>
string(1) "1"
["event_title"]=>
string(14) "New Year's Day"
[1]=>
string(14) "New Year's Day"
["event_desc"]=>
string(14) "Happy New Year"
[2]=>
string(14) "Happy New Year"
["event_start"]=>
string(19) "2015-01-01 00:00:00"
[3]=>
string(19) "2015-01-01 00:00:00"
["event_end"]=>
string(19) "2015-01-01 23:59:59"
[4]=>
string(19) "2015-01-01 23:59:59"
}
[1]=>
array(10) {
["event_id"]=>
string(1) "3"
[0]=>
string(1) "3"
["event_title"]=>
string(19) "Middle of the Mouth"
[1]=>
string(19) "Middle of the Mouth"
["event_desc"]=>
string(25) "The Middle of the January"
[2]=>
string(25) "The Middle of the January"
["event_start"]=>
string(19) "2015-01-16 00:00:00"
[3]=>
string(19) "2015-01-16 00:00:00"
["event_end"]=>
string(19) "2015-01-16 23:59:59"
[4]=>
string(19) "2015-01-16 23:59:59"
}
}
1
2
3
4
5
6
$stmt->bindColumn('event_id', $id);
$stmt->bindColumn('event_title', $title);

while($stmt->fetch(PDO::FETCH_BOUND)) {
echo $id . "\t" . $title . "\n";
}

以下为输出结果

1
2
1	New Year's Day
3 Middle of the Mouth
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
array(3) {
[0]=>
object(stdClass)#4 (5) {
["event_id"]=>
string(1) "1"
["event_title"]=>
string(14) "New Year's Day"
["event_desc"]=>
string(14) "Happy New Year"
["event_start"]=>
string(19) "2015-01-01 00:00:00"
["event_end"]=>
string(19) "2015-01-01 23:59:59"
}
[1]=>
object(stdClass)#5 (5) {
["event_id"]=>
string(1) "3"
["event_title"]=>
string(19) "Middle of the Mouth"
["event_desc"]=>
string(25) "The Middle of the January"
["event_start"]=>
string(19) "2015-01-16 00:00:00"
["event_end"]=>
string(19) "2015-01-16 23:59:59"
}
}
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
array(3) {
[0]=>
array(5) {
[0]=>
string(1) "1"
[1]=>
string(14) "New Year's Day"
[2]=>
string(14) "Happy New Year"
[3]=>
string(19) "2015-01-01 00:00:00"
[4]=>
string(19) "2015-01-01 23:59:59"
}
[1]=>
array(5) {
[0]=>
string(1) "3"
[1]=>
string(19) "Middle of the Mouth"
[2]=>
string(25) "The Middle of the January"
[3]=>
string(19) "2015-01-16 00:00:00"
[4]=>
string(19) "2015-01-16 23:59:59"
}
}

接下来的我用的不怎么多,简单介绍下

5、释放

bool PDOStatement::closeCursor ( void )释放到数据库服务的连接,以便发出其他SQL语句,但使语句处于一个可以被再次执行的状态。
等同于以下代码

1
2
3
4
do {
while ($stmt->fetch());
if (!$stmt->nextRowset()) break;
} while (true);

代码整合

总结上面,写一下完整的过程

1、带命名参数占位符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$dbn = "mysql:host=" . DB_HOST . ";charset=utf8;dbname=" . DB_NAME;

try{
$db = new PDO($dbn, DB_USER, DB_PASS);
}catch(Exception $e){
die($e->getMessage());
}

$sql = "select * from `event` where `event_id`=:id and `event_title`=:title";
$stmt = $db->prepare($sql);

$stmt->bindParam(":id", $id, PDO::PARAM_INT);
$stmt->bindParam(":title", $title, PDO::PARAM_STR);

if ($stmt->execute() == false){
//运行报错处理,多半是语法错误
}

$results = $stmt->fetchAll(PDO::FETCH_ASSOC); //$result存储返回的数据

$stmt->closeCursor();

2、带问号参数占位符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$dbn = "mysql:host=" . DB_HOST . ";charset=utf8;dbname=" . DB_NAME;

try{
$db = new PDO($dbn, DB_USER, DB_PASS);
}catch(Exception $e){
die($e->getMessage());
}

$sql = "select * from `event` where `event_id`=? and `event_title`=?";
$stmt = $db->prepare($sql);

$stmt->bindParam(1, $id, PDO::PARAM_INT);
$stmt->bindParam(2, $title, PDO::PARAM_STR);

if ($stmt->execute() == false){
//运行报错处理,多半是语法错误
}

$results = $stmt->fetchAll(PDO::FETCH_ASSOC); //$result存储返回的数据

$stmt->closeCursor();

还有一种则是不用bindParam()函数绑定参数,不过这种方法只能使用问号参数占位符,还有啊,个人感觉这种方法会让安全性降低= =

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$dbn = "mysql:host=" . DB_HOST . ";charset=utf8;dbname=" . DB_NAME;

try{
$db = new PDO($dbn, DB_USER, DB_PASS);
}catch(Exception $e){
die($e->getMessage());
}

$sql = "select * from `event` where `event_id`=? and `event_title`=?";
$stmt = $db->prepare($sql);

if ($stmt->execute(array($id, $title)) == false){
//运行报错处理,多半是语法错误
}

$results = $stmt->fetchAll(PDO::FETCH_ASSOC); //$result存储返回的数据

$stmt->closeCursor();

这就是一套基本的交互过程,不过本文以查询为例,插入和删除也是同样的,只是没有了获取数据这一过程。

The End~


Blog comments powered by Disqus