最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • PDO事务以及异常处理

    正文概述 转载于:掘金(陆小天)   2021-07-25   291

    一、PDO操作事务

    事务:是一个整体,要么一起执行,要么一起回滚 事务的特性:原子性、一致性、隔离性、永久性 需要将多个SQL语句作为一个整体执行,就需要使用到事务

    语法:

    例:

    创建测试数据:

    CREATE TABLE bank (
    	cardid char(4) PRIMARY KEY COMMENT '卡号',
        balance decimal(10,2) not null COMMENT '余额'
    )ENGINE=INNODB charset=utf8 COMMENT '银行卡号表'
    
    INSERT INTO bank VALUES ('1001',1000),('1002',1)
    

    效果:

    PDO事务以及异常处理


    PDO操作事务: 例题:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
    <?php
        if (!empty($_POST)) {
            $dsn='mysql:port=3306;host=localhost;dbname=data;charset=utf8';
            $pdo=new PDO($dsn, 'root', 'root');
            $out=$_POST['card_out']; // 转出卡号
            // echo $out;
            $in=$_POST['card_in'];  // 转进卡号
            $money=$_POST['money']; // 金额
            $pdo->beginTransaction(); // 开启事务
            $flag1=$pdo->exec("update bank set balance=balance-$money where cardid='$out'");
            $flag2=$pdo->exec("update bank set balance=balance+$money where cardid='$in'");
            $stmt = $pdo->query("select balance from bank where cardid='$out'"); // 查看转出的账号是否大于0
            $flag3=$stmt->fetchColumn()>=0?1:0;
            if ($flag1 && $flag2 && $flag3) {
                $pdo->commit(); // 提交事务
                echo '转账成功';
            }
            else {
                $pdo->rollBack(); // 回滚事务
                echo '转账失败';
            }
    
        }
    ?>
        <form action="" method="post">
            转出卡号:<input type="text" name="card_out"> <br>
            转入卡号:<input type="text" name="card_in"><br>
            金额:<input type="text" name="money">
            <input type="submit" value="提交">
    
        </form>
    </body>
    </html>
    
    

    效果: PDO事务以及异常处理


    二、PDO操作预处理

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

    预处理语句:

    执行预处理


    2.1 PDO中的预处理(位置占位符):

    方法一:

    <?php
        $dsn='mysql:port=3306;host=localhost;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(); // 执行预处理
        }
    
    
    

    效果: PDO事务以及异常处理


    方法二:

    <?php
        $dsn='mysql:port=3306;host=localhost;dbname=data;charset=utf8';
        $pdo=new PDO($dsn, 'root', 'root');
    
        // 创建预处理对象
        $stmt=$pdo->prepare('insert into bank values (?,?)'); // ?是占位符
        // 执行预处理
        $cards=[
            ['1005',520],
            ['1006',1000]
        ];
    
        foreach($cards as $card) {
            $stmt->bindValue(1, $card[0]);
            $stmt->bindValue(2, $card[1]);
        }
    
    
    

    效果: PDO事务以及异常处理


    方法三:

    <?php
        $dsn='mysql:port=3306;host=localhost;dbname=data;charset=utf8';
        $pdo=new PDO($dsn, 'root', 'root');
    
        // 创建预处理对象
        $stmt=$pdo->prepare('insert into bank values (?,?)'); // ?是占位符
        // 执行预处理
        $cards=[
            ['1007',520],
            ['1008',1000]
        ];
    
        foreach($cards as $card) {
            $stmt->execute($card); // 如果占位符的顺序和数组的顺序一致,可以直接传递参数
        } 
    
    
    

    效果: PDO事务以及异常处理


    2.2 PDO中的预处理(参数占位符)

    例:

    <?php
        $dsn='mysql:port=3306;host=localhost;dbname=data;charset=utf8';
        $pdo=new PDO($dsn, 'root', 'root');
    
        // 创建预处理对象
        $stmt=$pdo->prepare('insert into bank values (:p1,:p2)'); // :p1,:p2是参数占位符
        // 执行预处理
        $cards=[
            ['p1'=>'1009','p2'=>5200],
            ['p1'=>'1010','p2'=>10000]
        ];
        foreach($cards as $card) {
            /*
            // 方法一
            $stmt->bindParam(':p1', $card['p1']);
            $stmt->bindParam(':p2', $card['p2']);
            $stmt->execute();
             */
    
            // 方法二  当数组的下标和参数吗一致的时候就可以直接传递关联数组
            $stmt->execute($card);
    
        }
    

    效果: PDO事务以及异常处理


    小结: 1、?是位置占位符 2、参数占位符以冒号开头。 3、$stmt->bindParam()$stmt->bindValue()区别是前者只能是变量后者可以是变量或者是值。 4、预处理的好处:提高执行效率,提高安全性。

    三、PDO异常处理

    例:

    <?php
        try {
            $dsn='mysql:port=3306;host=localhost;dbname=data;charset=utf8';
            $pdo=new PDO($dsn, 'root', 'root');
            // 设置PDO错误模式属性,PDO自动抛出异常
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $pdo->query('select * from nesswk');
        } catch (PDOException $ex) {
            echo '错误信息: '.$ex->getMessage(),'<br>';
            echo '错误文件: '.$ex->getFile(),'<br>';
            echo '错误行号: '.$ex->getLine();
        }
    

    效果: PDO事务以及异常处理


    小结: 1、PDOException是PDO的异常类 2、实例化PDO会自动抛出异常 3、其他操作不会抛出异常,需要设置PDO的异常模式 4、PDO异常模式

    四、单例模式封装MyPDO类

    4.1 步骤

    1、单例模式 2、初始化参数 3、连接数据库 4、执行增删改 5、执行查询

    4.2 代码实现

    1、单例模式 2、初始化参数 3、连接数据库 如下:

    <?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';
                $this->pdo=$param['pdo']??'pdo';
            }
            //  初始化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->getMessage(),'<br>';
                    echo '错误编号: '.$ex->getCode(),'<br>';
                    echo '错误文件: '.$ex->getFile(),'<br>';
                    echo '错误行号: '.$ex->getLine(),'<br>';
                    exit;
                }
            }
        }
       
      // 测试
    $param=array(
    
    );
    $mypdo=MyPDO::getInstance($param);
    var_dump($mypdo);
    

    效果: PDO事务以及异常处理


    4、执行增删改 例:

    <?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() {
    
            }
            // 显示异常
            private function showException($ex, $sql='') {
                if ($sql!='') {
                    echo 'SQL语句失败<br>';
                    echo '错误的SQL语句是:'.$sql,'<br>';
                }
                echo '错误信息: '.$ex->getMessage(),'<br>';
                echo '错误编号: '.$ex->getCode(),'<br>';
                echo '错误文件: '.$ex->getFile(),'<br>';
                echo '错误行号: '.$ex->getLine(),'<br>';
                exit;
            }
    
            public static function getInstance($param=array()) {
                if (!self::$instance instanceof self) {
                    self::$instance=new self($param);
                }
                return self::$instance;
            }
            // 设置异常模式
            private function initException() {
                // 设置PDO错误模式属性,PDO自动抛出异常
                $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            }
            // 初始化参数
            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';
                $this->pdo=$param['pdo']??'pdo';
            }
            //  初始化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);
                }
            }
    
            // 执行增删改操作
            public function exec($sql) {
                try {
                    return $this->pdo->exec($sql);
                } catch (PDOException $ex) {
                    $this->showException($ex, $sql);
                }
            }
    
            // 获取自动增长的编号
            public function lastInsertId() {
                return '自动增长的编号是:'.$this->pdo->lastInsertId();
            }
            
        }
       
      // 测试
    $param=array(
    
    );
    $mypdo=MyPDO::getInstance($param);
    echo $mypdo->exec('delete from bank where cardid=1010');
    
    if ($mypdo->exec("insert into shows values (null,'b', 'bbb', CURRENT_TIMESTAMP)")) {
        echo $mypdo->lastInsertId();
    }
    
    

    效果: PDO事务以及异常处理 PDO事务以及异常处理 PDO事务以及异常处理


    5、执行查询

    例:

    <?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() {
    
            }
            // 显示异常
            private function showException($ex, $sql='') {
                if ($sql!='') {
                    echo 'SQL语句失败<br>';
                    echo '错误的SQL语句是:'.$sql,'<br>';
                }
                echo '错误信息: '.$ex->getMessage(),'<br>';
                echo '错误编号: '.$ex->getCode(),'<br>';
                echo '错误文件: '.$ex->getFile(),'<br>';
                echo '错误行号: '.$ex->getLine(),'<br>';
                exit;
            }
    
            public static function getInstance($param=array()) {
                if (!self::$instance instanceof self) {
                    self::$instance=new self($param);
                }
                return self::$instance;
            }
            // 设置异常模式
            private function initException() {
                // 设置PDO错误模式属性,PDO自动抛出异常
                $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            }
            // 初始化参数
            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';
                $this->pdo=$param['pdo']??'pdo';
            }
            //  初始化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);
                }
            }
    
            // 执行增删改操作
            public function exec($sql) {
                try {
                    return $this->pdo->exec($sql);
                } catch (PDOException $ex) {
                    $this->showException($ex, $sql);
                }
            }
    
            // 获取自动增长的编号
            public function lastInsertId() {
                return '自动增长的编号是:'.$this->pdo->lastInsertId();
            }
    
            // 判断匹配的类型
            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 (PDOException $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 (PDOException $ex) {
                    $this->showException($ex, $sql);
                }   
            }
    
            // 返回一行一列
            public function fetchColumn($sql) {
                try {
                    $stmt=$this->pdo->query($sql);
                    return $stmt->fetchColumn();
                } catch (PDOException $ex) {
                    $this->showException($ex, $sql);
                } 
                
            }
            
        }
       
      // 测试
    $param=array(
    
    );
    $mypdo=MyPDO::getInstance($param);
    // echo $mypdo->exec('delete from bank where cardid=1010');
    
    // if ($mypdo->exec("insert into shows values (null,'b', 'bbb', CURRENT_TIMESTAMP)")) {
    //     echo $mypdo->lastInsertId();
    // }
    
    $list=$mypdo->fetchAll('select * from news', 'obj');
    echo '<pre>';
    var_dump($list);
     
    echo '<br>';
    
    $list=$mypdo->fetchRow('select * from shows where id=1', 'obj');
    echo '<pre>';
    var_dump($list);
    
    echo '<br>';
    
    $list=$mypdo->fetchColumn('select count(*) from shows', 'obj');
    echo '<pre>';
    var_dump($list);
    

    效果: PDO事务以及异常处理



    起源地下载网 » PDO事务以及异常处理

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元