一、MySQLi扩展
1.1 mysqli扩展的基本介绍
(1) mysqli扩展和mysql扩展都可以完成对mysql数据库的操作.
(2) mysqli扩展可以看做是mysql扩展的升级版, i = improve
(3) mysqli扩展的性能比mysql扩展好,因此我们在新项目开发中,就不再使用mysql扩展, 新项目对mysql数据库的操作使用(mysqli, pdo).
(4) mysqli扩展支持面向对象开发, mysqli也支持面向过程
(5) 使用mysqli扩展前,需要引入一个dll文件, 该文件是 php_mysqli.dll, 该文件是安装php时有,在 ~/php/ext/php_mysqli.dll
1.2 mysqli 使用的细节说明
(1).如果执行的是dml语句,则返回bool
举例:

(2).从mysql_result 对象取出数据的方式有4种


小结:在实际的开发中,我们推荐使用第一种方式,因为第一种的可读性更好。
(3).细节-如何判断我们的dml语句是否真正影响了表

(4).如何获取到刚刚添加的自增长id的值

1.3 开发一个DAOMySQLi.class.php 工具类
基本的介绍: 封装一个更加完善的DAOMysqli.class.php 数据库操作类,方便我们以后可以在项目开发中直接使用。
使用的场景: 我们在一个项目中,会经常使用到对mysql数据库的各种操作(crud),我们可以将这些操作封装到一个类中,当我们需要操作数据库时,直接new一个对象然后使用对象来操作数据库即可。

说明:
(1) DAO, data access object, 数据访问对象,专门对mysql进行操作.
(2) DAOMySQLi.class.php 单例模式
代码实现:
<?php class DaoMySQLi{ //基本配置 private $_host; private $_user; private $_pwd; private $_dbname; private $_port; private $_charset; //单例对象 private static $_instance; //mysqli连接对象 private $_mySQLi; private function __construct(array $option){ $this->_host = isset($option['host'])?$option['host']:''; $this->_user = isset($option['user'])?$option['user']:''; $this->_pwd = isset($option['pwd'])?$option['pwd']:''; $this->_dbname = isset($option['dbname'])?$option['dbname']:''; $this->_port = isset($option['port'])?$option['port']:''; $this->_charset = isset($option['charset'])?$option['charset']:''; $this->_mySQLi = new MySQli($this->_host,$this->_user,$this->_pwd,$this->_dbname,$this->_port); $this->_mySQLi->set_charset($this->_charset); } //获取单例对象方法 public static function getSingleton(array $option){ if(!self::$_instance instanceof self){ self::$_instance = new self($option); } return self::$_instance; } public function query($sql){ $ret = $this->_mySQLi->query($sql); if($this->_mySQLi->errno){ return '查询失败:'.$this->_mySQLi->error; }else{ $ret_arr = array(); while($row = $ret->fetch_assoc()){ $ret_arr[] = $row; } return $ret_arr; } } public function update($sql){ $ret = $this->_mySQLi->query($sql); if($ret){ return '操作执行成功!'; }else{ return '操作执行失败!'.$this->_mySQLi->error; } } public function getLastId(){ return $this->_mySQLi->insert_id; } public function fetchone($sql){ $ret = $this->_mySQLi->query($sql); if($this->_mySQLi->errno){ return '查询失败:'.$this->_mySQLi->error; }else{ return $ret->fetch_assoc(); } } } ?>
1.4 mysqli扩展增强-事务控制
代码演示:


1.5mysqli扩展-批量执行sql语句
(1).先看一个需求
先看一个需求:有时,我们需要一次性执行多条sql语句,比如批量增加用户,这时如果单条单条的向mysql数据库发送sql指令,效率不高,这时可以考虑使用批量执行sql语句的方式.
传统的执行sql语句的方式是:

(2).批量执行sql语句的基本语法
$sqls = "$sq1;$sql2;$sql3..............";
$mySQLi->multi_query($sql3);
说明: 在拼接$sqls语句是,最后那个sql语句不要给;号.
(3).关于批量的执行dml语句的细节说明
1-> 批量执行sql语句分成两大类(dml[insert,update,delte], dql[select]), 两大类之间不要混用.
2-> 批量执行sql语句,返回的结果是以一条sql执行的结果为准, 当某条dml错误了,后面的代码就不执行, 但是错误之前的sql还是执行成功的.
批量执行select 语句代码演示:


1.6 mysqli扩展的-预处理技术
(1).看一个需求
现在需要向mysql数据库添加100个用户,请问如何实现?
(2).分析sql语句执行的原理
传统的sql语句执行的流程

使用了预处理技术sql语句执行的流程

(3).代码演示:
使用预处理插入数据->
<?php $conn = new MySQLi('localhost','root','q123456','testdb'); $sql = "insert into news values (null,?,?,?)"; $pre_sql = $conn->prepare($sql); $title = '孙哥激光笔'; $content = '孙笑川用激光笔射蔡徐坤'; $ctime = time(); $pre_sql->bind_param('ssi',$title,$content,$ctime); #注意除了第一个表示参数类型的参数以字符串形式传入,其他参数必须以变量名传入(引用传递)! $pre_sql->execute(); ?>
使用预处理查询->
<?php $conn = new MySQLi('localhost','root','q123456','testdb'); $sql = "select * from news"; $pre_sql = $conn->prepare($sql); $pre_sql->execute(); $pre_sql->bind_result($id,$title,$content,$ctime); #用以接收字段 while($pre_sql->fetch()){ echo $id.'-'.$title.'-'.$content.'-'.$ctime; echo '<br>'; }
(4).预处理的防止sql注入
看一个sql注入的实际案例


解决注入的方式有
(1) 使用PDO
(2) 使用一些好的工具类,工具类有自身的过滤sql语句的功能, 框架/函数
addslashes , mysqli_real_escape_string()
(3) 预处理方法
二、PDO扩展
2.1 PDO的基本介绍-示意图
说明:
PDO为我们访问数据库提供了轻量级、一致性的接口,也就是说通过PDO不仅可以访问mysql数据库,还能访问其他类型的数据库:oracle、mssql等,便于数据库的移植、迁移
示意图:

说明:
由于PDO是封装性的技术,是用来提升开发效率,将重复性的代码提取封装了,所以并没有对执行效率有多大的提升,不如mysqli扩展
2.2 PDO的基本使用
PDO扩展给我们提供了3个类,分别是:PDO、PDOStatement、PDOException
PDO类连接数据库,并对数据库进行增删改查操作

说明:
通过PDO连接、操作数据库,分为2种格式:
1->执行增删改的操作,通过pdo对象的exec()方法实现:通常返回受影响的记录数
2->执行查询操作通过pdo对象的query方法实现,返回的是PDOStatement类的对象,该对象代表一个预处理的语句对象,将sql语句的结构部分缓存了
PDOStatement对象提供了3个方法查询数据:
①fetch(),获取一条数据
②fetchAll(),获取所有数据
③fetchColumn(index),获取一列数据(一个字段的数据)
通过常量约束返回的数据格式:
PDO::FETCH_ASSOC,表示关联类型的数据
PDO::FETCH_NUM,表示索引数据
PDO::FETCH_BOTH,表示关联、索引数据


2.3 PDO对象错误信息
l 说明:
通过PDO对象的errorInfo、errorCode方法分别获得sql语句的错误信息、错误的代码号
l 方法:
errorInfo、erroCode
2.4 PDO对象-引号转移并包裹
l 说明:
引号转义并包裹,先将字符串中的引号转义(不再具有原来的意义),然后在外面再包裹一层引号
l 方法、演示:


2.5 PDO对象-事务处理
l 说明:
什么是事务:
一组DML语句的集合,事务有4个特点,原子性、一致性、隔离性、持久性
事务就是逻辑上的一组操作,这组操作的各个单元要么全部成功、那么全部失败,使用事务的时候,数据表的存储引擎必须是INNODB类型的
事务的使用步骤:
开启事务:beginTransaction()
如果各个单元全部成功:commit()
如果任何一个单元失败:rollback()
2.6 PDO对象-预处理
l 说明:
预处理,提前、预先处理sql,预处理执行的结果:先把sql语句的结构部分固定住,后期结构不会再变化,只能结果变化

l 使用预处理的优势:
(1) 对数据库的操作更加安全,将外部用户传递的数据使用占位符代替,不影响sql语句的结构
(2) 预处理会将sql语句的结构部分固定住,如果后期在执行类似的操作时,就直接使用上次编译好的(预处理)的语句,从而提升效率
2.7 PDO对象-lastInsertId
l 说明:
该方法是用来获得上次执行插入操作时产生的主键的值:$PDO_obj->lastInsertId()
2.8 PDOStatement对象
l 说明:
获得PDOStatement对象的方法:query()、prepare()
l PDOStatement对象提供的方法:
fetch()查询1条记录
fetchAll() 查询所有记录
fetchColumn() 查询一个字段的值
bindValue() 绑定参数(替换占位符)
execute() 执行预编译的sql语句
closeCursor() 关闭游标、指针(查询数据之后,将游标初始化,便于下次查询)
errorCode() 获得预编译sql语句中的错误代码
errorInfo() 获得预编译的sql语句中的错误信息
rowCount() 获得执行增删改受影响的记录数
2.9 封装PDO类
<?php interface I_DAO { //查询一条记录的方法 public function fetchRow($sql); //查询所有记录的方法 public function fetchAll($sql); //查询一个字段的值 public function fetchColumn($sql); //执行增删改的操作 public function exec($sql); //引号转义包裹的方法 public function quote($data); //查询刚刚插入的这条数据的主键 public function lastInsertId(); }
<?php require_once 'I_DAO.interface.php'; //首先,类要实现、完成接口规定的内容 class DAOPDO implements I_DAO { //私有的属性,将将来实例化的对象保存到该属性上 private static $instance; //DAOPDO类的单利对象 private $pdo; //PDO对象 //私有的构造方法,参数就是数据库的链接信息 private function __construct($option) { //在构造方法中,初始化操作(连接数据库) $host = isset($option['host'])?$option['host']:''; $user = isset($option['user'])?$option['user']:''; $pass = isset($option['pass'])?$option['pass']:''; $dbname = isset($option['dbname'])?$option['dbname']:''; $port = isset($option['port'])?$option['port']:''; $charset = isset($option['charset'])?$option['charset']:''; $dsn = "mysql:host=$host;dbname=$dbname;port=$port;charset=$charset"; try { $this->pdo = new PDO($dsn,$user,$pass); }catch (PDOException $e){ echo $e->getMessage(); } } //私有的克隆方法 private function __clone() { } //提供一个公共的静态方法生成对象 public static function getSingleton($option) { //如何生成单利的对象(只生成一个对象),先判断$pdo属性是否是当前类的实例 if(!self::$instance instanceof self){ self::$instance = new self($option); } return self::$instance; } //查询一条记录的方法 public function fetchRow($sql){ $pdo_statement = $this->pdo->query($sql); if($pdo_statement == false){ //说明sql语句有误,输出错误信息 $error = $this -> pdo -> errorInfo(); $err_str = "SQL语句有误,详细信息如下:<br>".$error[2]; echo $err_str; return false; } //执行到这里,说明sql语句没有问题 $result = $pdo_statement->fetch(PDO::FETCH_ASSOC); $pdo_statement -> closeCursor(); //关闭游标指针,便于下次查询 return $result; } //查询所有记录的方法 public function fetchAll($sql){ $pdo_statement = $this->pdo->query($sql); if($pdo_statement == false){ //说明sql语句有误,输出错误信息 $error = $this -> pdo -> errorInfo(); $err_str = "SQL语句有误,详细信息如下:<br>".$error[2]; echo $err_str; return false; } //执行到这里,说明sql语句没有问题 $result = $pdo_statement->fetchAll(PDO::FETCH_ASSOC); $pdo_statement -> closeCursor(); return $result; } //查询一个字段的值 public function fetchColumn($sql){ $pdo_statement = $this->pdo->query($sql); if($pdo_statement == false){ //说明sql语句有误,输出错误信息 $error = $this -> pdo -> errorInfo(); $err_str = "SQL语句有误,详细信息如下:<br>".$error[2]; echo $err_str; return false; } //执行到这里,说明sql语句没有问题 //因为将来查询的时候 sql语句如下:SELECT goods_name FROM goods WHERE goods_id = 1; //已经告诉数据库查询的是goods_name这个字段,所以fetchColumn的时候就不用再传递字段的索引 $result = $pdo_statement->fetchColumn(); $pdo_statement -> closeCursor(); return $result; } //执行增删改的操作,返回的是执行增删改受影响的记录数 public function exec($sql){ $result = $this->pdo->exec($sql); //如果sql语句出错了,输出错误信息,避免返回值是0的情况 if($result === false){ $error = $this->pdo->errorInfo(); $err_str = 'SQL语句有误,详细信息如下:<br>'.$error[2]; echo $err_str; return false; } //如果执行到这里说明,没有出错返回受影响的行数 return $result; } //引号转义包裹的方法,返回转义包裹之后的数据 public function quote($data){ return $this->pdo->quote($data); } //查询刚刚插入的这条数据的主键 public function lastInsertId(){ return $this->pdo->lastInsertId(); } }
浙公网安备 33010602011771号