思考:既然PDO这么强大,可以支持很多数据库,为什么一开始不直接使用PDO呢?
引入:PDO是一种纯面向对象方式实现的扩展,需要在大家掌握了php面向对象之后,才方便学习和理解
不过在实际开发中,现在基本都是通过PDO来实现数据库操作
PDO类基本应用【掌握】
定义:PDO是php Data Object的简称,代表PHP数据对象,是一种纯面向对象的方式实现的数据库操作扩展。
1.PDO类虽然提供了很多方法,但是常用的方法有以下几个
PDO::__construct() :实例化PDO对象的构造函数
PDO::exec() :执行一个写操作sql指令,返回受影响的行数
PDO::query():执行一个读操作sql指令,返回一个PDOStatment类对象,(后者进行数据解析操作)
PDO::errorCode()和PDO::errorInfo()获取上次错误的信息(错误码和错误描述数据)
2.PDO实例化对象:来利用构造方法__construct(string $dsn,string $user,string,$pass[,array $drivers])实现,构造方法由4个参数组成,
其中一般前三个为必须参数,第四个为可选。
$dsn:一个数据库基本信息字符串,包含数据库产品,主机地址等
- 驱动名字(数据库产品),使用英文:分割,如mysql:表示使用mysql数据库
- 驱动选项(主机地址),使用host=具体主机地址,跟在驱动名字之后,如‘mysqli:host=loclhost’。
- 驱动选项(端口),使用port=端口号,默认为3306可以不写,拼凑在驱动名字后,不区分先后顺序。
- 如'mysql:host=localhost;port=3306'或者'mysql:port=3306;host=localhost',使用分号和其他驱动分开。
- 驱动选项(数据库名字),使用dbname=数据库名字(可以视线没有)
- $user:用户名,如果数据库允许匿名用户出现,那么可以没有该参数(只有$dsn)
- $pass:密码,与用户名一样
- $drivers:PDO属性设置,是关联数组,利用PDO内部的常量进行设置
<?php //尝试连接mysql数据库PDO操作 //方案1 $pdo=new PDO('mysql:host=localhost;port=3306;dbname=senven','root','root'); var_dump($pdo); //方案2 $dsn='mysql:host=localhost;port=3306;dbname=senven'; $user='root'; $pass='root'; $pdo1=new PDO($dsn,$user,$pass); var_dump($pdo1); ?>
注意:在写参数的时候也可以把charset=utf8写上,这样在写操作或者读操作不会乱码了
//初始化PDO;增加错误拟制符,一致在初始化过程可能出现的错误(信息对接不上) function pdo_ini(){ //直接设置字符集 方便 $dsn='mysql:host=localhost;port=3306;dbname=senven;charset=utf8'; $obj=@new PDO($dsn,'root','root'); if(!$obj){ exit('数据库认证失败'); }else{ return $obj; } }
3.得到对象后,我们就可以利用PDO对象调用相关方法执行sql操作,exec执行数据返回SQL,query执行由结果返回sql
<?php $dsn='mysql:host=localhost;port=3306;dbname=senven'; $user='root'; $pass='root'; $pdo=new PDO($dsn,$user,$pass); //写数据 // $sql='delete from hylist where id=1'; // $result=$pdo->exec($sql); //删除成功 // var_dump($result); //返回1 删除成功 //读数据 $sql='select * from hylist'; $s=$pdo->query($sql); var_dump($s); //成功返回PDOStatements对象 否则返回false ?>
4.如果PDO对象在执行sql时出现错误,即sql本身有错误,那么可以通过PDO类蹄冻的errorCode()和errorInfo()
<?php $dsn='mysql:host=localhost;port=3306;dbname=senven'; $user='root'; $pass='root'; $pdo=new PDO($dsn,$user,$pass); $sql='delete from hyist where id=1000'; $row=$pdo->exec($sql); //错误判断,exec方法执行结果成功也存在返回0的情况,错误会返回false,所以要判定是否sql错误,需要判定结果为false //语法错误的时候会报错,如果id=1000在数据库中没有,不是sql语法错误 if($row===false){ echo '错误代码'.$pdo->errorCode().'<br>'; echo '错误原因'.$pdo->errorInfo()[2]; //errorInfo()返回数组,2下标代表错误具体信息 exit; //错误不需要继续执行程序 } //读取操作,也可以这么判定,query()成功返回PDOStatements对象,否则返回false ?>
总结:
1.PDO时一种外部提供的扩展,可以通过操作手册来协助学习使用
2.PDO类主要用来实现数据库的初始化操作和Sql指令的执行
3.sql执行的结果不论是写操作还是读操作都是可能出错的,因此需要进行错误处理
PDO写操作【掌握】
定义:写操作,即利用PDO实现数据库增删改操作,操作过程中要考虑到SQL本身可能出现的错误处理,以及对结果的操作
1.初始化PDO,每次操作都需要用到PDO实例化,封装执行
<?php //初始化PDO;增加错误拟制符,一致在初始化过程可能出现的错误(信息对接不上) function pdo_ini(){ $dsn='mysql:host=localhost;port=3306;dbname=senven'; $obj=@new PDO($dsn,'root','root'); if(!$obj){ exit('数据库认证失败'); }else{ return $obj; } } //返回得到的PDO对象 $obj=pdo_ini(); ?>
2.SQL通常应该是外部传入,外部需要的只是结果,不考虑过程,所以实际开发要考虑二次封装,即外部传入SQL,内部执行并控制错误,最终返回结果
<?php //初始化PDO;增加错误拟制符,一致在初始化过程可能出现的错误(信息对接不上) function pdo_ini(){ $dsn='mysql:host=localhost;port=3306;dbname=senven'; $obj=@new PDO($dsn,'root','root');
//设置字符集
$obj->exec('set names utf-8');
if(!$obj){ exit('数据库认证失败'); }else{ return $obj; } } //写操作 function pdo_exec($sql,$obj){ $result=$obj->exec($sql); //异常处理 if($result===false){ echo 'sql错误'.'<br>'; echo '错误代码'.$obj->errorCode(); echo '错误信息'.$obj->errorInfo()[2]; } } $obj=pdo_ini(); pdo_exec('delete from hylist wher id=10000',$obj); //提示语法错误 ?>
function pdo_exec($sql,$obj){ $result=$obj->exec($sql); //异常处理 if($result===false){ echo 'sql错误'.'<br>'; echo '错误代码'.$obj->errorCode(); echo '错误信息'.$obj->errorInfo()[2]; exit; }else{ return $result; //如果语法没有错误,返回受影响的行数 } } $obj=pdo_ini(); echo pdo_exec('delete from hylist where id=8',$obj); //提示语法错误
注意:一般写操作都是受影响行数,但是如果是插入操作,有时候需要新增记录的自增长ID,可以通过PDO::lastInsertId()来获取
$id=$pdo->lastInsertID(); echo '自增ID'.$id;
总结:
1.实际使用PDO的时候,都会进行二次封装,因为PDO的操作有很多本身不够完善
2.PDO类可以独立完成操作功能,而不需要使用其他两个工具类
3.PDO的写操作其实本质要注意的是执行Sql时可能出现的错误处理
4.写操作中唯一不同的时插入操作,因为可能需要获取自增长ID,此时需要多一个步骤
思考:如果要执行查询操作,光PDO一个类还不能完成,该如何实现呢?
引入:PDO的本质目的是为了进行初始化和SQL执行,而数据库数据结果通常还需要额外的功能才能真正的被PHP理解和访问
所以PDO查询之后得到的结果会自动传入到PDOstatement类对象中,我们可以在利用PDOstatement类的方法来实现数据的查询操作
PDO读操作【掌握】
定义:查询操作,即通过执行sql指令后,从数据库获得相应的数据,然后对数据加工变成PHP可识别的格式。
1.查询时建立在连接上,因此需要使用前面封装的初始化功能
<?php //初始化PDO;增加错误拟制符,一致在初始化过程可能出现的错误(信息对接不上) function pdo_ini(){ $dsn='mysql:host=localhost;port=3306;dbname=senven'; $obj=@new PDO($dsn,'root','root'); if(!$obj){ exit('数据库认证失败'); }else{ return $obj; } }
2.查询的sql也是可能出现问题部分,因此同样需要进行错误判定,另外PDO查询使用的时PDO::query()方法实现
function pdo_query($sql,$obj){ $state=$obj->query($sql); //错误判定 if($state===false){ echo '错误代码'.$obj->errorCode().'<br>'; echo '错误信息'.$obj->$obj->errorInof()[2]; }
3.此时查询处理啊的结果是一个对象,不能提供任何PHP可访问的数据结果,还需要对结果进行处理。而我们查询数据时候通常是两种操作,根据具体条件获取一条记录或多条记录,因此返回的
数据是不同的,解决方案也有多种方式,1.创建多个函数来显示不同效果;2.创建一个函数,但是通过参数来控制实现不同效果
//读取PDOstatement类对象中的数据 //参数1需要传一个对象,是否显示所有参数 默认显示一行为true function pdo_get($statement,$date=true){ //判定使用不同dePDOstatement类对象方法 if($date){ //获取一行数据 return $statement->fetch(); }else{ //获取全部数据 return $statement->fetchAll(); }
5.fetch系列方法获取返回的数据是重复的,数据的索引方法和关联方式各出现了一次,而实际进行开发数据展示时通常时通过数据表字段名作为下标进行数据查看,所以此时可以通过设定fetch
系列的条件fetch_style来实现
PDOStatement::fetch([int $fetch_style,int $cursor_orientation=PDO::FETCH_ORI_NEXT[,int $cursor_offset=0]]);
手册上有介绍 ,这里我们使用assoc关联数组就可以了
//读取PDOstatement类对象中的数据 //参数1需要传一个对象,是否显示所有参数 默认显示一行为true function pdo_get($statement,$date=true){ //判定使用不同dePDOstatement类对象方法 if($date){ //获取一行数据,使用默认关联数组显示 return $statement->fetch(PDO::FETCH_ASSOC); }else{ //获取全部数据 return $statement->fetchAll(PDO::FETCH_ASSOC); } } $pdo=pdo_ini(); $sql='select * from hylist'; $state=pdo_query($sql,$pdo); $result=pdo_get($state); echo $result['id'].$result['hyname'] //通过关联数组下标形式显示出来
总结:
1.查询操作时通过PDO::query()执行查询sql得到PDOStatement对象,然后PDOStatement对象下有一系列fetch方法可以实现数据查询,得到PHP可以时别的数组数据
2.PDO实现查询通常也需要进行二次封装,保证SQL执行安全,也方便用户获取目标数据