PDO数据访问抽象层:
我们使用的mysqli是针对mysql这个数据库扩展的一个类,如果要用到别的数据库的话就可以用PDO来做
1.操作数据库
先来代码
<!--PDO--> <!--数据访问抽象层--> <!--可以访问其他数据库--> <!--具有事务功能--> <!--带有预处理语句功能(防止sql注入攻击功能)--> <?php //1.造PDO对象 $dsn = "mysql:dbname=heiheihei;host=localhost"; //冒号前面的是驱动名称(mysql),后面是参数:dbname=连接哪一个数据库;连接到本机 $pdo = new PDO($dsn,"root","12345678"); //root(数据库用户名,密码) //2.写sql语句 $sql = "select * from mydb"; //查询语句 //3.执行sql语句 //$stm = $pdo->query($sql); //执行查询语句 //4.从PDOStatement对象里面读取数据 //$arr = $stm->fetch(PDO::FETCH_ASSOC); //返回关联数组,即返回一个索引为结果集列名的数组 //$arr = $stm->fetch(PDO::FETCH_BOTH); //关联加索引,即返回一个索引为结果集列名和以0开始的列号的数组 //$arr = $stm->fetch(PDO::FETCH_NUM); //返回索引的数组,即返回一个索引为以0开始的结果集列号的数组 //$arr = $stm->fetch(PDO::FETCH_OBJ); //返回一个属性名对应结果集列名的匿名对象 //缺省为 PDO::ATTR_DEFAULT_FETCH_MODE 的值,即默认 //如果是PDOStatement::fetchAll,即代表一次性读出所有数据 var_dump($arr); ?>
输出:
调用一下fetch里面的参数为 PDO::FETCH_ASSOC
输出attr,则返回一个索引为结果集列名的数组:
调用一下fetch里面的参数为 PDO::FETCH_NUM
输出attr,则返回一个索引为结果集列名和以0开始的列号的数组:
调用一下fetch里面的参数为 PDO::FETCH_OBJ
输出attr,则返回一个属性名对应结果集列名的匿名对象:
改为fetchALL(PDO::FETCH_OBJ)也可以,它是把所有数据都可以查到:
用PDO来做个添加语句:
<?php //1.造PDO对象 $dsn = "mysql:dbname=heiheihei;host=localhost"; //冒号前面的是驱动名称(mysql),后面是参数:dbname=连接哪一个数据库;连接到本机 $pdo = new PDO($dsn,"root","12345678"); //root(数据库用户名,密码) //2.写sql语句 $sql = "insert into mydb VALUES ('虾','123','小虾',0)"; //增删改语句 //3.执行sql语句 $arr = $pdo->exec($sql); //执行添加语句,exec返回影响的行数 //4.从PDOStatement对象里面读取数据 var_dump($arr); ?>
exec是用来执行其他语句,他返回的是受影响的行数
图:
显示了一个1,证明影响了1行数据;
如果失败了,运行后会显示0
再看一下,数据库内,已经添加成功:
2.事务功能
事务功能即能够控制语句同时成功或同时失败,失败时可以回滚
事务有三个基本的方法:
PDO::beginTransaction() - 启动一个事务:将下面的代码看作一个事务
commit - 提交事务:是将开始和提交中间的代码看作一个事务一起执行提交
PDO::rollBack() - 回滚一个事务:如果有问题就回滚,没有问题就不用回滚,回滚就是还原
代码:
<?php $dsn = "mysql:dbname = mydb;host=localhost"; //数据源 $pdo = new PDO($dsn,"root","123"); //造对象 //改事务模式 //1.将PDO的错误类型设为异常模式(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION ) $pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //try尝试运行里面代码 try { //开启事务 $pdo->beginTransaction(); $sql = "insert into mydb VALUES ('西','123','小西',0)"; $sqll = "insert into mydb VALUES ('虾','123','小虾',0)"; $pdo->exec($sql); $pdo->exec($sqll); //提交事务 $pdo->commit(); } //catch抓住异常.控制异常。$e代表异常的数值 catch(Exception $e) { // echo "有错误"; //回滚操作!!! //如果发现有错误,回滚rollback! $pdo->rollBack(); } //最终执行,必执行 //final //{ //无论有没有一场出现,该代码都会执行 //} ?>
在我的数据库里面帐号是主键
西是可以添加上的,但是虾有重复是加不上的,因为有事务功能 ,要么一起成功,要么一起失败,所以这两条数据都不会成功
运行完成,查看数据库:
果然一条都没有成功!
如果把虾改成对的:
$sql = "insert into mydb VALUES ('西','123','小西',0)"; $sqll = "insert into mydb VALUES ('东','123','小东',0)";
一起添加成功!!
3.预处理语句防止SQL注入:
他是分两次来发送到输出,就不会出现注入攻击了
(1)占位符“?”方法:
<?php $dsn = "mysql:dbname=heiheihei;host=localhost"; $pdo = new PDO($dsn,"root","12345678"); //框架 $sql = "insert into mmaa VALUES (?,?)"; //写一个预处理语句,在写参数的地方用占位符“?”代替 //将预处理语句扔到服务器等待执行,返回PDOStatomont对象;prepare准备,等待执行 $stm = $pdo->prepare($sql); //第二次将变量(参数)扔到服务器的SQl语句相应位置,给预处理语句绑定参数。binparam绑定参数 //第一个参数第二个参数是 $stm->bindParam(1,$id); $stm->bindParam(2,$name); //赋值 $id = 5; $name = "孙"; //执行 $stm->execute();
这是一个添加语句,让我们来看看添加成功
如果数据过多,上面这种方法会极其麻烦,所以还有一种简单方法
<?php $dsn = "mysql:dbname=heiheihei;host=localhost"; $pdo = new PDO($dsn,"root","12345678"); //框架 $sql = "insert into mmaa VALUES (?,?)"; //写一个预处理语句,在写参数的地方用占位符“?”代替 //将预处理语句扔到服务器等待执行,返回PDOStatomont对象;prepare准备,等待执行 $stm = $pdo->prepare($sql); //定义一个数组,必须是索引数组 $arr = aarray("8","邵"); //执行 $stm->execute($arr);
这上面的这种方法很智能,并且很简便,它可以自动把参数仍到该扔到的地方
(2)名称占位法...
这种方法一目了然,知道该填什么参数
代码:
首先我设一个添加的页面:
<body> <h1>添加一条数据</h1> <form action="bbb.php" method="post"> <div>id:<input type="text" name="id"/></div> <div>姓名:<input type="text" name="name"/></div> <input type="submit" value="点击添加"/> </form> </body>
然后我去做处理页面:
<?php $dsn = "mysql:dbname=heiheihei;host=localhost"; $pdo = new PDO($dsn,"root","12345678"); //预处理语句,括号里不是?了 $sql = "insert into mmaa VALUES (:id,:name)"; $stm = $pdo->prepare($sql); //执行,$_post里面有id跟name的值,所以直接把post扔进去就好了 $stm->execute($_POST);
添加图:
点击添加,查看数据库:
添加成功了,代码量非常少
PDO常用方法及其应用
PDO::query() 主要是用于有记录结果返回的操作,特别是SELECT操作
PDO::exec() 主要是针对没有结果集合返回的操作,如INSERT、UPDATE等操作
PDO::prepare() 主要是预处理操作,需要通过$rs->execute()来执行预处理里面的SQL语句,这个方法可以绑定参数,功能比较强大(防止sql注入就靠这个)
PDO::lastInsertId() 返回上次插入操作,主键列类型是自增的最后的自增ID
PDOStatement::fetch() 是用来获取一条记录
PDOStatement::fetchAll() 是获取所有记录集到一个集合
PDOStatement::fetchColumn() 是获取结果指定第一条记录的某个字段,缺省是第一个字段
PDOStatement::rowCount() :主要是用于PDO::query()和PDO::prepare()进行DELETE、INSERT、UPDATE操作影响的结果集,对PDO::exec()方法和SELECT操作无效。
防注入攻击原理:
当调用 prepare() 时,查询语句已经发送给了数据库服务器,此时只有占位符 ? 发送过去,没有用户提交的数据;当调用到 execute()时,用户提交过来的值才会传送给数据库,他们是分开传送的,两者独立的,SQL攻击者没有一点机会。