1 PDO介绍

方法一:mysql扩展【这种方式php7已经淘汰】
方法二:mysqli扩展
方法三:PDO扩展

1.1 连接数据库方式

1.2 PDO介绍

PDO(PHP Data Object)扩展为PHP访问各种数据库提供了一个轻量级,一致性的接口。无论访问什么数据库,都可以通过一致性的接口去操作。

1.3 开启PDO扩展

开启PDO连接MySQL扩展

1
extension=php_pdo_mysql.dll

2 PDO核心类

1、PDO类:表示PHP和数据库之间的一个连接
2、PDOStatement 类
第一:表示执行数据查询语句(select ,show)后的相关结果集
第二:预处理对象
3、PDOException类:表示PDO的异常

1561083447524.png

3 实例化PDO对象

语法

1
__construct($dsn,用户名,密码)

3.1 DSN

DSN:data source name,数据源名称,包含的是连接数据库的信息,格式如下:

1
dsn=数据库类型:host=主机地址;port=端口号;dbname=数据库名称;charset=字符集

数据库类型:

1
2
3
4
MySQL数据库    =>  mysql:
oracle数据库 => oci:
SQL Server =>sqlsrv:
具体驱动类型参见手册“PDO驱动”

3.2 实例化PDO

实例化PDO的过程就是连接数据库的过程

1
2
3
4
<?php
$dsn='mysql:host=localhost;port=3306;dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
var_dump($pdo); //object(PDO)#1 (0) { }

3.3 注意事项

1、如果连接的是本地数据库,host可以省略

1
2
3
4
<?php
$dsn='mysql:port=3306;dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
var_dump($pdo); //object(PDO)#1 (0) { }

2、如果使用的是3306端口,port可以省略

1
2
3
4
<?php
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
var_dump($pdo); //object(PDO)#1 (0) { }

3、charset也省略,如果省略,使用的是默认字符编码

1
2
3
4
<?php
$dsn='mysql:dbname=data';
$pdo=new PDO($dsn,'root','root');
var_dump($pdo);

4、dbname也可以省略,如果省略就没有选择数据库

1
2
3
4
<?php
$dsn='mysql:';
$pdo=new PDO($dsn,'root','root');
var_dump($pdo);

5、host、port、dbname、charset不区分大小写,没有先后顺序

6、驱动名称不能省略,冒号不能省略(因为冒号是驱动名组成部分),数据库驱动只能小写

4 使用PDO

4.1 执行数据操作语句

方法:$pdo->exec($sql),执行数据增、删、改语句,执行成功返回受影响的记录数,如果SQL语句错误返回false。

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
<?php
//1、实例化PDO
$dsn='mysql:host=localhost;port=3306;dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
//2执行数据操作语句
//2.1 执行增加
/*
if($pdo->exec("insert into news values (null,'bb','bbbbbb',unix_timestamp())"))
   echo '自动增长的编号是:'.$pdo->lastInsertId (),'<br>';
*/
//2.2 执行修改
//echo $pdo->exec("update news set title='静夜思' where id in (3,4)");
//2.3 执行删除
//echo $pdo->exec('delete from news where id=5');\
//2.4 完善
$sql="update news set title='静夜思1' where ids in (3,4)";
$rs=$pdo->exec($sql);
if($rs){
   echo 'SQL语句执行成功<br>';
   if(substr($sql, 0,6)=='insert')
       echo '自动增长的编号是:'.$pdo->lastInsertId (),'<br>';
   else
       echo '受到影响的记录数是:'.$rs,'<br>';
}elseif($rs===0){
   echo '数据没有变化<br>';
}elseif($rs===false){
   echo 'SQL语句执行失败<br>';
   echo '错误编号:'.$pdo->errorCode(),'<br>';
   //var_dump($pdo->errorInfo());
   echo '错误信息:'.$pdo->errorInfo()[2];
}

4.2 执行数据查询语句

方法:$pdo->query($sql),返回的是PDOStatement对象

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
<?php
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
//1、执行数据查询语句
$stmt=$pdo->query('select * from products');
//var_dump($stmt);       //object(PDOStatement)
//2、获取数据
//2.1 获取二维数组
//$rs=$stmt->fetchAll(); //默认返回关联和索引数组
//$rs=$stmt->fetchAll(PDO::FETCH_BOTH);     //返回关联和索引数组
//$rs=$stmt->fetchAll(PDO::FETCH_NUM);     //返回索引数组
//$rs=$stmt->fetchAll(PDO::FETCH_ASSOC);   //返回关联数组
//$rs=$stmt->fetchAll(PDO::FETCH_OBJ);       //返回对象数组

//2.2 获取一维数组,匹配完成后指针下移一条
//$rs=$stmt->fetch();     //关联和索引数组
//$rs=$stmt->fetch(PDO::FETCH_NUM);   //索引数组
//例题:通过while循环获取所有数据
/*
while($row=$stmt->fetch(PDO::FETCH_ASSOC)){
   $rs[]=$row;
}
echo '<pre>';
var_dump($rs);
*/

//3.3 匹配列:匹配当前行的第n列,列的编号从0开始,匹配完毕后指针下移一条
//echo $stmt->fetchColumn(); //获取当前行的第0列
//echo $stmt->fetchColumn(1); //获取当前行的第1列

//3.4 总行数,总列数
/*
echo '总行数:'.$stmt->rowCount(),'<br>';
echo '总列数:'.$stmt->columnCount();
*/

//3.5 遍历PDOStatement对象(PDOStatement对象是有迭代器的)
foreach($stmt as $row){
   echo $row['proname'],'-',$row['proprice'],'<br>';
}
1
stdClass类是所有PHP类的父类

4.3 PDO操作事务

事务:是一个整体,要么一起执行,要么一起回滚

事务的特性:原子性,一致性,隔离性,永久性

需要将多个SQL语句作为一个整体执行,就需要使用到事务

语法

1
2
3
start transaction 或 begin       开启事务
commit 提交事务
rollback 回滚事务

小结:

1
2
3
$pdo->beginTransaction()   开启事务
$pdo->commit () 提交事务
$pdo->rollBack() 回滚事务

4.4 PDO操作预处理

5 PDO异常处理

1
2
3
4
5
6
7
8
9
10
11
12
<?php
try{
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
//这是PDO错误模式属性,PDO自动抛出异常
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->query('select * from newsssssss'); //自动抛出异常
} catch (PDOException $ex) {
echo '错误信息:'.$ex->getMessage(),'<br>';
echo '错误文件:'.$ex->getFile(),'<br>';
echo '错误行号:'.$ex->getLine();
}

小结:

1、PDOException是PDO的异常类

2、实例化PDO会自动抛出异常

3、其他操作不会抛出异常,需要设置PDO的异常模式

4、PDO异常模式

1
2
3
4
PDO::ERRMODE_EXCEPTION	抛出异常
PDO::ERRMODE_SILENT 中断
PDO::ERRMODE_WARNING 警告

6 单例模式封装MyPDO类

6.1 步骤

1、单例模式

2、初始化参数

3、连接数据库

4、执行增删改

5、执行查询

a)返回二维数组

b)返回一维数组

c)返回一行一列

6.2 代码实现

第一部分:单例、初始化参数、实例化PDO

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
<?php
class MyPDO{
   private $type;      //数据库类别
   private $host;      //主机地址
   private $port;      //端口号
   private $dbname;    //数据库名
   private $charset;   //字符集
   private $user;      //用户名
   private $pwd;       //密码
   private $pdo;       //保存PDO对象
   private static $instance;
   private function __construct($param) {
       $this->initParam($param);
       $this->initPDO();
  }
   private function __clone() {
  }
   public static function getInstance($param=array()){
       if(!self::$instance instanceof self)
           self::$instance=new self($param);
       return self::$instance;
  }
   //初始化参数
   private function initParam($param){
       $this->type=$param['type']??'mysql';
       $this->host=$param['host']??'127.0.0.1';
       $this->port=$param['port']??'3306';
       $this->dbname=$param['dbname']??'data';
       $this->charset=$param['charset']??'utf8';
       $this->user=$param['user']??'root';
       $this->pwd=$param['pwd']??'root';
  }
   //初始化PDO
   private function initPDO(){
       try{
           $dsn="{$this->type}:host={$this->host};port={$this->port};dbname={$this->dbname};charset={$this->charset}";
           $this->pdo=new PDO($dsn, $this->user, $this->pwd);
      } catch (PDOException $ex) {
           echo '错误编号:'.$ex->getCode(),'<br>';
           echo '错误行号:'.$ex->getLine(),'<br>';
           echo '错误文件:'.$ex->getFile(),'<br>';
           echo '错误信息:'.$ex->getMessage(),'<br>';
           exit;
      }
  }
}
//测试
$param=array(
);
$mypdo= MyPDO::getInstance($param);
var_dump($mypdo);

第二部分:数据操作部分

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
<?php
class MyPDO{
   private $type;      //数据库类别
   private $host;      //主机地址
   private $port;      //端口号
   private $dbname;    //数据库名
   private $charset;   //字符集
   private $user;      //用户名
   private $pwd;       //密码
   private $pdo;       //保存PDO对象
   private static $instance;
   private function __construct($param) {
       $this->initParam($param);
       $this->initPDO();
       $this->initException();
  }
   private function __clone() {
  }
   public static function getInstance($param=array()){
       if(!self::$instance instanceof self)
           self::$instance=new self($param);
       return self::$instance;
  }
   //初始化参数
   private function initParam($param){
       $this->type=$param['type']??'mysql';
       $this->host=$param['host']??'127.0.0.1';
       $this->port=$param['port']??'3306';
       $this->dbname=$param['dbname']??'data';
       $this->charset=$param['charset']??'utf8';
       $this->user=$param['user']??'root';
       $this->pwd=$param['pwd']??'root';
  }
   //初始化PDO
   private function initPDO(){
       try{
           $dsn="{$this->type}:host={$this->host};port={$this->port};dbname={$this->dbname};charset={$this->charset}";
           $this->pdo=new PDO($dsn, $this->user, $this->pwd);
      } catch (PDOException $ex) {
           $this->showException($ex);
           exit;
      }
  }

   //显示异常
   private function showException($ex,$sql=''){
       if($sql!=''){
           echo 'SQL语句执行失败<br>';
           echo '错误的SQL语句是:'.$sql,'<br>';
      }
       echo '错误编号:'.$ex->getCode(),'<br>';
       echo '错误行号:'.$ex->getLine(),'<br>';
       echo '错误文件:'.$ex->getFile(),'<br>';
       echo '错误信息:'.$ex->getMessage(),'<br>';
  }
   //设置异常模式
   private function initException(){
       $this->pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
  }

   //执行增、删、改操作
   public function exec($sql){
       try{
           return $this->pdo->exec($sql);
      } catch (PDOException $ex) {
           $this->showException($ex, $sql);
           exit;
      }
  }
   //获取自动增长的编号
   public function lastInsertId(){
       return $this->pdo->lastInsertId();
  }
}
//测试
$param=array(

);
$mypdo= MyPDO::getInstance($param);
//echo $mypdo->exec('delete from news where id=6');
if($mypdo->exec("insert into news values (null,'11','1111',unix_timestamp())"))
   echo '自动增长的编号是:'.$mypdo->lastInsertId ();

第三部分:数据查询部分

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
<?php
class MyPDO{
  ...

   //判断匹配的类型
   private function fetchType($type){
       switch ($type){
           case 'num':
               return PDO::FETCH_NUM;
           case 'both':
               return PDO::FETCH_BOTH;
           case 'obj':
               return PDO::FETCH_OBJ;
           default:
                return PDO::FETCH_ASSOC;
      }
  }
   //获取所有数据 ,返回二维数组
   public function fetchAll($sql,$type='assoc'){
       try{
           $stmt=$this->pdo->query($sql);  //获取PDOStatement对象
           $type= $this->fetchType($type); //获取匹配方法
           return $stmt->fetchAll($type);
      } catch (Exception $ex) {
           $this->showException($ex, $sql);
      }
  }
   //获取一维数组
   public function fetchRow($sql,$type='assoc'){
       try{
           $stmt=$this->pdo->query($sql);  //获取PDOStatement对象
           $type= $this->fetchType($type); //获取匹配方法
           return $stmt->fetch($type);
      } catch (Exception $ex) {
           $this->showException($ex, $sql);
           exit;
      }
  }
   //返回一行一列
   public function fetchColumn($sql){
       try{
            $stmt=$this->pdo->query($sql);
           return $stmt->fetchColumn();
      } catch (Exception $ex) {
           $this->showException($ex, $sql);
           exit;
      }

  }

}
//测试
$param=array(

);
$mypdo= MyPDO::getInstance($param);
//echo $mypdo->exec('delete from news where id=6');
/*
if($mypdo->exec("insert into news values (null,'11','1111',unix_timestamp())"))
   echo '自动增长的编号是:'.$mypdo->lastInsertId ();
*/

//$list=$mypdo->fetchAll('select * from news');
//$list=$mypdo->fetchRow('select * from news where id=1');
$list=$mypdo->fetchColumn('select count(*) from news');
echo '<pre>';
var_dump($list);

3、$stmt->bindParam()和$stmt->bindValue()区别

4、预处理的好处

1
2
a)提高执行效率
b)提高安全性

2、参数占位符以冒号开头

1、?是位置占位符

小结:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
$dsn='mysql:dbname=data;charset=utf8';
$pdo=new PDO($dsn,'root','root');
//创建预处理对象
$stmt=$pdo->prepare("insert into bank values (:p1,:p2)");   //:p1,:p2是参数占位符
//执行预处理
$cards=[
  ['p1'=>'1003','p2'=>500],
  ['p1'=>'1004','p2'=>1000]
];
foreach($cards as $card){
   //方法一:
   /*
   $stmt->bindParam(':p1', $card['p1']);
   $stmt->bindParam(':p2', $card['p2']);
   $stmt->execute();
    */
   //方法二:但数组的下标和参数名一致的时候就可以直接传递关联数组
   $stmt->execute($card);
}

PDO中的预处理——参数占位符

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
<?php
   $dsn='mysql:dbname=data;charset=utf8';
   $pdo=new PDO($dsn,'root','root');
   //创建预处理对象
   $stmt=$pdo->prepare("insert into bank values (?,?)");   //?是占位符
   //执行预处理
   $cards=[
      ['1003',500],
      ['1004',100]
  ];
   foreach($cards as $card){
       //绑定参数,并执行预处理,
       //方法一:
       /*
       $stmt->bindParam(1, $card[0]); //占位符的位置从1开始
       $stmt->bindParam(2, $card[1]);
       $stmt->execute();               //执行预处理
        */
       //方法二:
       /*
       $stmt->bindValue(1, $card[0]);
       $stmt->bindValue(2, $card[1]);
       $stmt->execute();
        */
       //方法三:如果占位符的顺序和数组的顺序一致,可以直接传递数组
       $stmt->execute($card);
  }

PDO中的预处理——位置占位符

1
execute 预处理名字 [using 变量]

执行预处理

1
prepare 预处理名字 from 'sql语句'

预处理语句:

预处理好处:编译一次多次执行,用来解决一条SQL语句多次执行的问题,提高了执行效率。

复习MySQL中预处理


本站由 RuntimeBroker 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本"页面"访问 次 | 👀总访问 次 | 总访客