pdo php解释器与数据库之间的语言翻译器 使用以及简单的尝试封装成php 单例对象

<?php

/**
 * 今日 2021 4 24 PDO
 * 接下来
 * 讲PDO
 * 为什么要讲PDO
 * 接下来讲一个场景
 *
 * 客户端访问服务器
 *
 * 客户端暂时不用我们写
 * 我们只做
 * 服务器php这部分
 *
 * 做好以后服务器要不要连数据库啊
 * 要连数据库
 * 下面问题来了
 *
 * 我将来开发了
 * 一个框架
 * 我开发的框架是不是php
 * 的
 * 我开发好了
 *
 * 我开发框架
 * 开发好了
 * 交给你
 * 去使用
 *
 * 比如说
 * 我们将来
 * 学 tp框架
 * 学 laravel 框架
 *
 * 这些框架是不是开发好了
 * 给我们使用的
 *
 * 假设我们将开也开发一个框架
 * 供别人使用
 * 那么
 * 你怎么知道
 *
 * 别人一定是连的
 * mysql 数据库呢
 *
 * 数据库它除了
 * mysql 还有其他数据库的
 *
 * SQL Server
 * Oracle
 * ...
 *
 * 人家开发的 laravel
 * 或 tp 框架
 * 到了
 * 市面上使用
 *
 * 其实 tp 框架开发者
 * 它早就知道了
 *
 * 我开发出来的时候
 * 这些人不一定是连mysql的
 *
 * 那么请问我这个框架
 * 怎么开发
 *
 * 也就是说我压根不知道
 * 它连什么数据库
 *
 * 你想像一个场景
 * 一个人说话 所有数据库都能听懂
 * 哦
 * 难道 PDO就是 语言转换器?
 * 就是 翻译?
 *
 * 这个翻译自动的
 * 翻译到各个语言;里面去
 * 这个翻译就叫
 * PDO
 * PDO是连接数据库的一种方式
 * 这个PDO能连接各种各样的数据库
 *
 * 你php 只要
 * 操作 PDO
 *
 * PDO他会帮你自动的去连接各种各样的数据库
 *
 * 那么这就是我们为什么要学
 * PDO 的原因
 *
 * 所有的框架
 * 底层连接都是PDO的
 *
 * 你们马上学
 * TP框架了
 * TP框架里面也是PDO的
 *
 * 我们以前学的mysqli连接
 * 他只能连接什么数据库啊
 *
 * 他只能连mysql
 * 它其它数据库连不了
 *
 * 所以说我想要
 * 连各种各样的数据库
 * 该怎么办
 *
 * 那就是要连
 * 让PDO来连
 *
 * 来总结一下
 * 其实连接数据库的方式有几种
 * mysql 连接 在php7之后已经淘汰了
 * mysqli 连接 在php7之后支持
 *
 * 以后php 操纵PDO就行了
 * PDO会去操纵不同的数据库
 *
 * PDO 是PHP的数据对象
 * 也是连接数据库的一种方式
 * 其实也是一个拓展
 *
 * PDO
 * mysql
 * mysqli
 * 3个都是PHP拓展
 *
 * 下面开始使用PDO了
 *
 * 首先 开启PDO的拓展
 * 在 D:\phpStudy\PHPTutorial\php\php-7.2.1-nts 中
 * 打开 php.ini php配置文件
 *
 *
 * extension=php_pdo_mysql.dll pdo连mysql
 *
 * ;extension=php_pdo_oci.dll pdo连Oracle
 *
 * ;extension=php_pdo_odbc.dll 万能连接方式 所有数据库都能连
 *
 * 我们用 mysql 使用 pdo连mysql
 *
 * 万能连接是有缺陷的
 *
 * PDO拓展中有 3个核心类
 *
 *
 * PDO 类
 * PDOStatement 类 结果集保存的地方
 * PDOException 类 执行异常 保存的地方
 *
 * 可以new 出来类对象 并调用方法
 * 只要你 new 了 就连接上了
 *
 * 连接上了
 * 是不是要执行数据
 * 查询语句
 *
 * 只要你执行数据查询语句
 * 他是不是返回一个结果集啊
 * 这个结果集 是什么类型呢
 *
 * 他的结果集数据
 * 全部都封装在 PDOStatement 类 里面
 * PDOException
 *
 * 要想使用开启PDO 拓展
 * 我这又是 默认开启了(解开注释即可)
 *
 * extension=php_pdo_mysql.dll pdo连mysql
 *
 * 连接上之后就执行增删改查了
 *
 * 增删改查没什么好说的
 * PDO里面有好多的方法
 *
 * 然后如果你有异常了
 * 你就 在 PDOException 里面
 *
 * 一切异常的父类就是 PDOException 类
 *
 * 下面依次来讲这三个类
 * PDO 连接
 * PDOStatement 存着结果集
 * PDOException 存着 异常
 *
 * 下面就来
 * 实例化
 * 连接对象
 * 一实例化就能
 *
 * 连接数据库了
 * 我们怎么来连接数据库
 *
 *
 */
// $dsn = 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
// $pdo = new PDO($dsn, 'root', 'root');
/**
 * dsn: data source name
 * 数据源名称
 * 
 * 数据源有 mysql
 *          oci
 *          sqlsrv
 * 
 * 我们只开启了  mysql 所以
 * $dsn = 'mysql:host=location;port=3306;dbname=data;charset=utf8';
 * 
 * //如果连本地 host=location; 可省略
 * //如果端口号是3306  port=3306;    也可省略
 * charset=utf8' 不设字符编码也能连接上
 * dbname=data;  数据库链接的时候也可以先不写 还是能连接上
 * 
 * $dsn = 'mysql:'; 最多节省成这样 否则报错
 * 
 * mysql: 是一个整体 代表连接 mysql 数据库 不能用大写(数据库驱动名称)
 * 其余不区分大小写
 * 
 * 
 * $dsn里分号隔开的内容 没有先后 顺序 先写那个都可以('mysql:'必须写在最前面)
 * 命令行的 -h -u -p 也是没有先后顺序
 * 
 */

// var_dump($pdo); //object(PDO)#1 (0) { }
//连接上了

//PDO 实例化好以后 那对象就有了
// 对象有了
//说明 我们就连接上了
//连接上以后 我们要执行数据的 
//操作语句 增删改查 了

//1增
// echo  '受影响的记录数', $pdo->exec("INSERT into news values (null,'bb','bbbbb',unix_timestamp())"); //返回的是1 代表受影响的记录数 

//$pdo 就是这个好人 将类都写好了
//我们直接调就可以了

// echo '<br>增加成功,id为:' . $pdo->lastInsertId();
// echo '<hr>';

//2.改
// echo '受影响的记录数', $pdo->exec("UPDATE  news set title='静夜思' where id in (3,4); "); //返回的是2 代表受影响的记录数 

//$pdo 就是这个好人 将类都写好了
//我们直接调就可以了

// echo '<br>修改成功';
// echo '<hr>';

//3.删
// echo '受影响的记录数', $pdo->exec("DELETE from news  where id in 9; "); //返回的是2 代表受影响的记录数 

//$pdo 就是这个好人 将类都写好了
//我们直接调就可以了

// echo '<br>删除成功';
// echo ' <hr>';
// echo '增删改综合<hr>';

//1,2,3综合 完善
// $sql = "UPDATE  news set title='静夜思' where ids in (1,2); ";
// $rs = $pdo->exec($sql);
// if ($rs) {
// echo 'SQL语句执行成功<br>';
// if (substr($sql, 0, 6) == 'insert') {
// echo '增加成功,id为:' . $pdo->lastInsertId();
// } else {
// echo '受影响的记录数为: ', $rs;
// }
// } elseif ($rs === 0) {
// echo '受影响的记录数为: 0 ';
// } elseif ($rs === false) {
// echo 'SQL语句执行失败<br> ';
// echo '错误码: ', $pdo->errorCode(), '<br>';
/* var_dump($pdo->errorInfo());
    array(3) { [0]=> string(5) "42S22" [1]=> int(1054) [2]=> string(38) "Unknown column 'ids' in 'where clause'" }*/
// echo '错误信息: ' . $pdo->errorInfo()[2];
// }
// echo ' <hr>查';
// 4.查
//上面讲的方法全是 pdo类对象的方法 增删改
//接下来 讲的方法 全部是 PDOStatement类对象里的方法 保存查询结果集
// $sql = "SELECT * from products ";
//1.执查询行语句
// $stmt = $pdo->query($sql);
// var_dump($stmt);
// object(PDOStatement)#2 (1) {
//  ["queryString"]=> string(23) "SELECT * from products " 
// } 

//2.获取查询结果数据(二维数组)
// $rs = $stmt->fetchAll(PDO::FETCH_BOTH); //获取所有 关联和索引 数组 
// (默认PDO::FETCH_BOTH)
// $rs = $stmt->fetchAll(4); //获取所有 关联和索引 数组 
// (默认 4)

// $rs = $stmt->fetchAll(PDO::FETCH_NUM); //获取所有  索引 数组
// $rs = $stmt->fetchAll(3); //获取所有  索引 数组

// $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); //获取所有  关联 数组
// $rs = $stmt->fetchAll(2); //获取所有  关联 数组

// $rs = $stmt->fetchAll(PDO::FETCH_OBJ); //获取所有  关联 数组x 对象√
// $rs = $stmt->fetchAll(5); //获取所有  关联 数组x 对象√
echo '<pre>';


//2.1 获取一维数组
// $rs = $stmt->fetch(PDO::FETCH_BOTH); //获取一个 关联和索引 数组 
// (默认PDO::FETCH_BOTH) 再获取一次 为所有中的第二个 关联和索引 数组
// $rs = $stmt->fetch(4); //获取一个 关联和索引 数组 
// (默认 4)

// $rs = $stmt->fetch(PDO::FETCH_NUM); //获取一个  索引 数组 
//  再获取一次 为所有中的第二个  索引 数组
// $rs = $stmt->fetch(3); //获取一个  索引 数组 

// $rs = $stmt->fetch(PDO::FETCH_ASSOC); //获取一个  关联 数组 
//  再获取一次 为所有中的第二个  关联 数组
// $rs = $stmt->fetch(2); //获取一个  关联 数组 

// $rs = $stmt->fetch(PDO::FETCH_OBJ); //获取一个  关联 数组x 对象√
//  再获取一次 为所有中的第二个  关联 数组x 对象√
// $rs = $stmt->fetch(5); //获取一个  关联 数组x 对象√

//写个例题 通过while 循环获取所有数据
// while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { //循环请求每一个关联数组
//     $rs[] = $row; //请求到了就添加到  $rs里面
// } //这样就获取到了 所有 关联数组


//2.2 获取单行某列
// $rs = $stmt->fetchColumn(0); //获取当前行的第0(不写默认)列 
// 当前行的 第0列 为id id=1 再次查询为下一行 的id=2
// $rs = $stmt->fetchColumn(1); //第一行 的第1列 为 proname 
//牛奶
//即使变换了 列 每一行依旧会累计


// var_dump($rs);
//2.3 获取 总 行/列 数
// echo '总行数: ' . $stmt->rowCount(), '<br>'; //总行数: 77
// echo '总列数: ' . $stmt->columnCount(), '<br>'; //总列数: 7


//2.4遍历 PDOStatement 对象
/**
 * 下面我写一个东西
 * 你给我说它的原理是什么
 * 
 */
// foreach ($stmt as $index => $item) {
// var_dump($index, $item);
//$item 所有结果集 的每一项
// $index 0开始 到76 总数据77条(1开始)

/**为什么在 PDOStatement 对象中能遍历出数组呢
 * 因为  PDOStatement 对象里面有 迭代器
 * 返回了 数组 给我们遍历
 */
// }


/**
 * 下面我给大家小结一下
 * 我给大家讲的是查询数据
 * 当你用 query 查询完了以后 它返回的是
 * PDOStatement 对象
 * 那么数据在 这个
 * PDOStatement 对象里面 也就是上面的  $stmt
 * 
 * $stmt就是这个  PDOStatement 对象
 * 我把这个对象匹配成二维数组
 * .....
 * 等后面查询详细操作
 * 前面都有详细记录
 * 
 * 
 * 
 * 来
 * 下面我们说一下
 * 另一个功能
 * PDO的这个事务操作
 * 
 * 事务: 是一个整体,要么一起执行,要么一起回滚.
 * 特性: 原子性,一致性,隔离性,永久性
 * 
 * 需要将多个SQL语句作为一个整体执行,
 * 就需要使用到事物
 * 
 * 语法:
 * start transaction 或 begin  #开启事物
 * commit                      #提交事物
 * rollback                    #回滚事物
 * 
 * 接下来我们学习怎么用 PDO
 * 操纵事务
 * 
 * 它的思想 是没有变化的
 * 问题是 mysql 事务回滚还没学完
 * 
 * 所以我并不知道 原来的 思想
 * 
 * 首先news表的 表单类型 是 InnoDB
 * 
 * data/news/右键/更多表操作/变更表单类型为  
 * 
 * 说明这个news 是可以使用事务的
 * 
 * 算了
 * 我们举一个贴近生活的例子
 * 银行 转账 吧
 * 
 * 在data数据库中 新创建一个 bank 表
 * 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);
 * 
 * bank 表 展示为
 * cardid    balance
 * 1001       1000.00
 * 1002          1.00
 */
?>
<html>
<?php
// if (!empty($_POST)) { //如果 post 提交不为空
//     //上面已经连了 data 数据库
//     //这里不再重复

//     $out = $_POST['card_out']; //要转出的卡号
//     $in = $_POST['card_in']; //要转入的卡号
//     $mon = $_POST['money']; //要转出的金额

//     $pdo->beginTransaction(); //开启事务
//     //事务 1
//     $flag1 = $pdo->exec("UPDATE bank set balance=balance-$mon where cardid=$out");
//     //事务 2
//     $flag2 = $pdo->exec("UPDATE bank set balance=balance+$mon where cardid=$in");

//     //事务 3
//     $stmt = $pdo->query("SELECT balance from bank where cardid=$out");
//     //转完 之后的 余额大于等于零 否回滚
//     $flag3 = $stmt->fetchColumn() >= 0 ? true : false;
//     //同 查询 余额是否足够转出 一样 还更简单些 步骤少些      

//     if ($flag1 && $flag1 && $flag3) {
//         $pdo->commit(); //提交事务
//         echo '转账成功';
//     } else {
//         $pdo->rollBack(); //回滚事务
//         echo '转账失败';
//     }
// }
?>
<!-- <form action="" method="post">
    转出卡号<input type="text" name="card_out" id=''><br>
    转入卡号<input type="text" name="card_in" id=''><br>
    金额<input type="text" name="money" id=''><br>
    <input type="submit" value='提交'><br>
</form> -->

</html>
<?php
/**
 * 下面我小结一下
 * pdo 操作事务有3 个方法
 * 
 * 1.$pdo->beginTransaction(); //开启事务
 * 2.$pdo->commit(); //提交事务
 * 3.$pdo->rollBack(); //回滚事务
 * 
 * 
 * 好下面我们说一下
 * PDO操作预处理
 * 呃
 * 我们首先
 * 
 * 将mysql时讲过预处理
 * 呃 我后面没学完
 * 
 * 为什么讲预处理呢
 * 
 * 好处: 一次编译多次执行,减少了词法分析
 *         语法分析编译的过程
 * 
 * 预处理语句:
 * prepare 预处理名字 from 'sql语句'
 * 
 * 执行预处理
 * execute 预处理名字 [using 变量]
 * 
 * 就用 data数据库 的 bank表来
 * 举例子吧
 */
//创建 预处理对象
// $stmt = $pdo->prepare("INSERT into bank values (?,?)");
//自动返回 PDOStatement  对象 $stmt
//PDOStatement 不仅表示 查询结果集 对象
//             同时还表示 预处理   对象

// ? 表示位置占位符


//执行预处理

//方法一 用的
// $cards = [
//     ['1003', 500],
//     ['1004', 100]
// ];

//方法二 用的
// $cards = [
//     ['1005', 6000],
//     ['1006', 700]
// ];

//方法三 用的
$cards = [
    ['1007', 7000],
    ['1008', 800]
];
// foreach ($cards as $index => $item) {
//用foreach遍历的方式绑定预处理SQL语句

// 方法一
// $stmt->bindParam(1, $item[0]);
//   绑定  (第一个问号 ,  卡号)
// $stmt->bindParam(2, $item[1]);
//                     只能放变量
//   绑定  (第二个问号 ,  余额)

// $stmt->execute();
//  执行预处理

// 方法二
// $stmt->bindValue(1, $item[0]);
// //                   可以放值
// $stmt->bindParam(2, $item[1]);
// $stmt->execute();


// 居然还有方法三
//如果数组的先后 顺序
//就是 占位符的 先后顺序
// $stmt->execute($item); //['1007', 7000]
//"INSERT into bank values (?,?)"
// 直接(传递数组)执行就好了
//他会一一对应
// }
/*本来  data数据库中 bank表为
cardid  balance
1001    900.00
1002    101.00
变成了
cardid  balance
1001    900.00
1002    101.00
1003    500.00
1004    100.00

这就是批量处理 
这有点像函数
这个是


下面来 看看方法二
在方法一的结果上又变成了
cardid  balance
1001     900.00
1002     101.00
1003     500.00
1004     100.00
1005    6000.00
1006     700.00

好像这两种方法
没啥区别呀

   // $stmt->bindParam(2, $item[1]);
    //                     只能放变量

   $stmt->bindValue(1, $item[0]);
    //                   可以放值

    这样来看  bindValue 好多了
    既可以放值 也能放变量

下面又来 看看方法三
在方法二的 结果上又变成了
cardid  balance
1001     900.00
1002     101.00
1003     500.00
1004     100.00
1005    6000.00
1006     700.00
1007    7000.00
1008     800.00


下面我来小结一下
说这个

为什么
pdo 要预处理呢
因为我要多次
执行一个相同的操作

连续插入好多个相同记录
例子里是 
        卡号 和 余额

 每次都用sql语句的话
 词法分析语法分析太多了
 我们能不能用
 预处理


 那么在
 pdo 里面
 除了
 提供了
 一个位置占位符
 之外还提供了一个
 参数占位符

先前的 ? 是 位置占位符
 $stmt = $pdo->prepare("INSERT into bank values (?,?)");
 
 现在的参数占位符
*/
// $stmt = $pdo->prepare("INSERT into bank values (:p1,:p2)");
//  :p1,:p2 是参数占位符
$cards = [
    ['p1' => '哈哈哈', 'p2' => 7000],
    ['p2' => 800, 'p1' => '爱仕达']
];
foreach ($cards as $index => $item) {
    //方法一
    // $stmt->execute($item); // ['p1' => '哈哈哈', 'p2' => 7000]
    //下标一一对应 可直接传递(关联数组) 

    //方法二
    // $stmt->bindParam(':p1', $item['p1']);
    // //                      只能放变量
    // $stmt->bindParam(':p2', $item['p2']);
    // $stmt->execute();

    //方法三 
    // $stmt->bindValue(':p1', $item['p1']);
    // //                      可以放值
    // $stmt->bindParam(':p2', $item['p2']);
    // $stmt->execute();
}
/**
 * 新增两行参数 
 * cardid  balance
 * '哈哈哈'  7000
 * '爱仕达'  800
 * 
 * 
 * 
 * 那么下面
 * 呢
 * 我们总共是
 * 3个类
 * pdo类            讲完了  连接 
 * PDOStatement 类  讲完了 结果集/预处理
 * 还差一个异常类
 * PDOException
 * 
 * 既然有异常
 * 那么肯定会有 异常处理了
 * 
 * 其它的语言只有
 * 异常处理
 * 没有错误处理
 * 
 * 但是 唯独 PHP
 * 同时兼具 异常/错误 处理的功能
 * 
 * 这两个
 * 哪个用的多呢
 * 还是错误处理用的多
 * 
 * 异常处理用的少
 * 为什么 异常处理
 * php用的少呢
 * 
 * 是因为
 * PHP里面 太烦人了
 * 每次有错误都要手动抛出
 * 
 * 其它语言都是自动跑
 * php你如果不手动抛出
 * 它这个catch 就 捕获不到错误
 * 
 * 但是如果有个好人
 * 开了个插件 / 拓展
 * 
 * 能够自动抛出异常
 * 
 * 这个问题是不是就解决了
 * 
 * 那么我们来看一看
 * PDO 能不能帮我们
 * 自动抛出
 * 
 * 这么说了 应该是能
 * 
 */
// try {

// $dsn = 'mysql:host=localhost;port=3306;dbname=datas;charset=utf8';
// $pdo = new PDO($dsn, 'root', 'root');
// $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//设置 PDO 为有错误抛出 异常
//默认是 除了 new PDO以外  都不会自动抛出 和捕获错误

// $pdo->query('暗讽'); //现在执行错误查询的语句 也会抛出错误了
//说你的 sql 语法错误
// } catch (PDOException $ex) {
//不同的是我们抛出的是 
// PDOException 异常
//而不是 Exception 普通异常
//而且php 的异常需要手动抛出
// echo '错误信息: ', $ex->getMessage(), '<br>';
// echo '错误文件: ', $ex->getFile(), '<br>';
// echo '错误行号: ', $ex->getLine(), '<br>';
// }
/*
只有 PDO 连接失败才会触发 mysql 语句执行错误不会触发

错误信息: SQLSTATE[HY000] [1049] Unknown database 'datas'
错误文件: D:\phpStudy\PHPTutorial\WWW\PDO.php
错误行号: 724

默认情况下
除了 new PDO以外  都不会自动抛出 和捕获错误

既然说了默认说明是可以更改的

PDO中 可设置 3中错误处理模式
PDO::ERRMODE_EXCEPTION 抛出异常
PDO::ERRMODE_WARNING   警告
PDO::ERRMODE_SILENT    终止
PDO::ERRMODE_NONE      啥也不干 不算处理模式


我们小结一下:
1.PDOException 是PDO的异常类
2.只有实例化 new PDO出错会默认抛出异常
3.其它操作不会,需要设置
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    //设置 PDO 为有错误抛出 异常        抛出异常/警告/终止/啥也不干 
    //                                   4种选择 
    //默认是 除了 new PDO以外  都不会自动抛出 和捕获错误
*/


/**
 * 
 * 好同学们
 * 我们再来用
 * 单例模式封装一下 MyPDO 类
 * 
 * 就是在PDO基础上进行二次封装
 * 步骤:
 * 1.单例模式
 * 2.初始化参数
 * 3.连接数据库
 * 4.执行增伤改
 * 5.执行查询
 *  a)返回二维数组
 *  b)返回一维数组
 *  c)返回一行一列
 * 
 * 为什么还要
 * 封装单例
 * 这样不是已经能用了么
 * 最多 封装下单例 阻止二次实例化
 * 
 * 但是后面的功能都写好了吧
 * 
 * 
 * 
 */


echo '<hr>';
echo '<hr>';
echo '<hr>';
class MyPDO
{
    private $type;    //mysql: 数据库类别
    private $host;    //localhost 主机地址
    private $port;    //3306 端口号
    private $dbname;  //data 要连接的数据库名称
    private $charset; //utf8 字符集
    private $user;    //root 用户名
    private $pwd;     //root 密码
    private $pdo;     // 保存 pdo 对象

    private static $instance;
    private function __construct($param)
    {
        $this->initParam($param); //初始化参数
        $this->initPDO($param); //初始化 PDO对象
        $this->initParamException(); //启动 sql语句报错提示
    }
    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'] ?? 'localhost'; //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($param)
    {
        try {
            $dsn = "{$this->type}:
            host={$this->host};
            port={$this->port};
            dbname={$this->dbname};
            charset={$this->charset}";

            //上面千万不能有空格 里面

            // $dsn = 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';

            $this->pdo = new PDO($dsn, $this->user, $this->pwd);
            // $this->pdo = new PDO($dsn, 'root', 'root');


            // $pdo = new PDO($dsn, 'root', 'root');
        } catch (PDOException $ex) {
            // Exception 是 PDOException
            //的父类 也能捕获 PDO的异常
            $this->showException($ex); //显示异常
            exit;
        }
    }

    //执行 增删改 操作
    public function exec($sql)
    {
        try {

            return  $this->pdo->exec($sql);
        } catch (PDOException $ex) {
            $this->showException($ex, $sql); //显示异常
            exit;
        }
    }

    //报错 复用 显示异常
    private function showException($ex, $sql = '')
    {
        if ($sql !== '') {
            echo 'SQL语句执行失败<br>';
            echo '错误的SQL语句是: ' . $sql, '<br>';
        }
        echo '错误信息: ', $ex->getMessage(), '<br>';
        echo '错误文件: ', $ex->getFile(), '<br>';
        echo '错误行号: ', $ex->getLine(), '<br>';
        echo '错误码: ', $ex->getCode(), '<br>';
    }

    //设置 PDO 为有错误抛出 异常
    private function initParamException()
    {
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        //设置 PDO 为有错误抛出 异常
        //默认是 除了 new PDO以外  都不会自动抛出 和捕获错误
    }

    //增加时  获取的自动增长的编号 并返回
    public function lastInsertId()
    {
        return $this->pdo->lastInsertId();
    }

    //判断 要查询 关联/索引/关联索引 数组
    private function fetchType($type)
    {
        switch ($type) {
                // case 'assoc':
                //     return PDO::FETCH_ASSOC; //2
            case 'num':
                return PDO::FETCH_NUM; //3
            case 'both':
                return PDO::FETCH_BOTH; //4
            case 'obj':
                return PDO::FETCH_OBJ; //5
            default:
                return PDO::FETCH_ASSOC; //2
        }
    }

    //获取查询结果集 , 返回二维数组
    public function fetchAll($sql, $type = 'assoc')
    {
        try {
            $stmt = $this->pdo->query($sql); //获取PDOStatement 查询结果集对象
            $type = $this->fetchType($type); //判断 要查询 关联/索引/关联索引 数组
            return  $stmt->fetchAll($type); //规定 返回 关联/索引/关联索引 数组
            // fetchAll() 获取全部数组
        } catch (PDOException $ex) {
            $this->showException($ex, $sql);
            exit;
        }
    }




    //获取查询结果集  , 返回一维数组
    public function fetchRow($sql, $type = 'assoc')
    {
        try {
            $stmt = $this->pdo->query($sql); //获取PDOStatement 查询结果集对象
            $type = $this->fetchType($type); //判断 要查询 关联/索引/关联索引 数组
            return  $stmt->fetch($type); //规定 返回 关联/索引/关联索引 数组
            // fetchAll() 获取一条数组
        } catch (PDOException $ex) {
            $this->showException($ex, $sql);
            exit;
        }
    }

    //获取查询结果集  , 返回单行单例
    public function fetchColumn($sql, $type = 'assoc')
    {
        try {
            $stmt = $this->pdo->query($sql); //获取PDOStatement 查询结果集对象
            return  $stmt->fetchColumn(0); //规定 返回 关联/索引/关联索引 数组
            // fetchColumn(0) 获取一行数组 0列
        } catch (PDOException $ex) {
            $this->showException($ex, $sql);
            exit;
        }
    }
}
//测试
$param = array(
    // 'user' => 'aa'
    // 'pwd' => 'bb'

);

$mypdo = MyPDO::getInstance($param);
// var_dump($mypdo);
// object(MyPDO)#7 (0) {}
// $mypdo->exec("DELETE from news where id= 11");


// if ($mypdo->exec("INSERT into news values (null,'11','1111',unix_timestamp())")) {
//     echo '自动增长的编号是: ' . $mypdo->lastInsertId();
// }

// $list = $mypdo->fetchAll('select * from news', 'obj'); //不传 'obj' 默认关联数组  获取全部查询结果集
// echo '<pre>';
// var_dump($list);


// $list = $mypdo->fetchRow('SELECT * from news where id=1', 'obj'); //不传 'obj' 默认关联数组  获取 一行 查询结果集
// echo '<pre>';
// var_dump($list);

$list = $mypdo->fetchColumn('SELECT count(*) from news'); //不传 'obj' 默认关联数组  获取 单行单列 查询结果集
echo '<pre>';
var_dump($list);//string(2) "77"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qwer22215

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值