PDO详解

一、PDO诞生的意义

PHP对数据库支持的抽象度不够,接口不统一。每一种数据库环境都必须重新定义数据库的操作。在这种背景下,统一操作接口PDO诞生了。

在PHP中,有三种数据库连接方式:

(1)mysql 最常用,过程式风格的一种应用

(2)mysqli,mysql函数的增强版,提供面向对象和过程两种风格的API,增加了预编译和参数绑定等新的特性

(3)PDO统一抽象接口,更类似于mysqli

二、PDO常用函数

PDO中包含三个预定义类:PDO、PDOStatement和PDOException

(1)PDO类中的常用方法有:

beginTransaction():开启事务机制

commit():提交事务

exec():执行一条SQL语言并返回影响的行数

prepare():为执行准备一条SQL语句,返回语句执行后的联合结果集

query():执行一条SQL语句并返回一个结果集

rollBack():回滚一个事务

getAttribute():获取一个数据库连接属性

setAttribute():设置一个数据库连接属性

(2)PDOStatement类中常用方法有:

bindParam():绑定一个PHP变量到一个预处理语句中的参数

execute():执行一条预处理语句

fetch():从结果集中取出一行

fetchAll():从结果集中取出一个包含所有行的数组

fetchColumn():返回结果集中某一列的数据

(3)PDOException是对exception类的简单重写,这里不作介绍

三、PDO的简单使用

1.在windows系统下,开启PDO需要在php.ini中将

;extension=php_pdo_mysql.dll

前面的分号去掉,如果使用的数据库不是mysql,则将对应的数据库扩展配置前面的分号去掉

在linux或者ngnix系统下,开启PDO也需要在php配置文件中将对应的拓展前的注释符号去掉。

2.在数据库中建立test数据库和一张test表,如下图所示

在服务器目录下新建一个php脚本如下:

<?php

try{

//配置数据源,数据库服务器IP和数据库名

$dsn="mysql:host=127.0.0.1;dbname=test";

$db=new PDO($dsn,"root","");


//设置异常可捕获

$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

 

$db->exec("set names utf8");

//插入新数据

$sql="insert into test(name) values('HeCheng')";

$db->exec($sql);

 

}catch(PDOException $err){

echo $err->getMessage();

}

?>

结果如下:

三、PDO预编译和参数绑定

预编译:

<?php

try{

//数据库地址,数据库,数据库账户和密码

$dsn="mysql:host=127.0.0.1;dbname=test";

$db=new PDO($dsn,"root","");

 

$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

$insert=$db->prepare("insert into test(name) values(?);");

//插入

$insert->execute(Array("HeChengLei"));

 

//异常语句

//$insert->execute(Array("ZhangJun","1983-09-21"));

 

//查找

$select=$db->prepare("select * from test");

$select->execute();

var_dump($select->fetchAll(PDO::FETCH_ASSOC));

 

}catch(PDOException $err){

echo $err->getMessage();

}

?>

结果:

参数绑定:

<?php

$name='HeCheng';

$dsn="mysql:host=127.0.0.1;dbname=test";

 

$db=new PDO($dsn,"root","");

 

//用?代替param

$sth=$db->prepare("select * from test where name=?");

//参数绑定

$sth->bindParam(1,$name,PDO::PARAM_STR,12);

$sth->execute();

var_dump($sth->fetchAll(PDO::FETCH_ASSOC));

 

//用:param代替param

$sth=$db->prepare("select * from test where name=:name");

$sth->bindParam(':name',$name,PDO::PARAM_STR,12);

$sth->execute();

var_dump($sth->fetchAll(PDO::FETCH_ASSOC));

?>

结果:

PDO最大的特点就是引入了预编译和参数绑定,二者的关系其实就是同一件事情的不同阶段,参数绑定使用bindParam()函数传入参数。

四、SQL注入与参数绑定

1.SQL注入的原理

MySQL注入又称为SQL Injection,通过构造特定的SQL语句获取权限外的数据。

SQL注入的原理非常简单,就是在原有SQL语句上添加一些布尔条件语句。

例,在浏览器中执行下列请求:

http://127.0.0.1/index.php?name=HeCheng

数据库执行对应的SQL语句如下

select * from test where name=’HeCheng’;

但如果一些不良客户构造这样的请求如:

http://127.0.0.1/index.php?name=HeCheng or ‘1=1

数据库即执行下列SQL语句

select * from test where name=’HeCheng’; or 1=1;

将会把数据库表中所有客户的信息查找出来,造成客户信息泄露

2.SQL注入的防范

实际上,SQL注入的技术含量并不高,防范也非常简单。

在处理客户输入的信息时,如果是整型变量,就是用intval()把传入的参数转化为一个数值。对于字符型变量,可以使用addslashes()把所有单引号、双引号、反斜线和空字符转化为含有反斜线的溢出字符。对于可能出现的特殊字符,进行转译和过滤。

3.使用PDO参数绑定防范SQL注入

PDO的参数绑定就是防范SQL注入的一种好办法。

其函数原型为:

<?php

function bindParam(&$sql,$location,$var,$type){

switch ($type) {

default:

case 'STRING':

$var=addslashes($var);

$var="'".$var."'";

break;

case "INTEGER":

case "INT":

$var=(int)$var;

//还可以拓展多种类型

}

for($i=1,$pos=0;$i<=$location;$i++)

$pos=strpos($sql,'?',$pos+1);

 

$sql=substr($sql,0,$pos).$var.substr($sql,$pos+1);

}

?>

五、PDO的事务机制

PDO中使用beginTransaction()创建事务,使用commit()或者rollback()结束事务。

在使用beginTransaction()后,如果事务中有异常出现或者没有提交事务即关闭数据库连接和结束脚本,事务会自动回滚,即终止前的所有语句都不会生效。这体现了事务的原子性。

如:

$db->beginTransaction();

$db->exec(“insert into test(name) values(‘ZhangDa’)”);

$db->exec(“insert test(name) values(‘WangGang’)”);//这条语句是错误的,无法执行

$db->commit();

在这段代码中,因为使用了事务机制,第二个插入语句错误会导致第一个插入语句也不会生效。

六、PDO的效率问题

PDO比mysql、mysqli的连接更为稳定,但在效率上却不一定比直连更好。而且在实际应用中,数据库迁移的情况不是很多,PDO更无法保证一次编写,到处运行。所以推荐在新应用中考虑使用PDO,在旧的应用中则没有必要进行重构。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 打造专属插件之Easy Slider Bar

    引用 <link rel="stylesheet" type="text/css" href="./index.css"> <div id="slider"><...

    lonelydawn
  • Vuex从入门到精通(三)

    开始 前言 这一节,我们将通过一个实战案例 : 动态展示从后台返回的新闻列表 允许用户根据来源, 和 内容&标题 中的关键字对新闻列表进行筛选 来加...

    lonelydawn
  • canvas星空的2d绘制示例

    一切尽在注释里: <!DOCTYPE html> <html> <head>     <meta charset="utf-8"></meta>     <t...

    lonelydawn
  • PHP中用PDO查询Mysql来避免SQL注入风险的方法

    当我们使用传统的 mysql_connect 、mysql_query方法来连接查询数据库时,如果过滤不严,就有SQL注入风险,导致网站被攻击,失去控制。虽然可...

    企鹅号小编
  • 数据库(PDO 对象常用方法)

    PDO 是一个“数据库访问抽象层”,作用是统一各种数据库(MySQL、MSSQL、Oracle、DB2、PostgreSQL……)的访问接口,能轻松的在不同的数...

    用户5745385
  • bootstrap 多级菜单 注册登录

    li class=dropdown a class=dropdown-toggle data-toggle=dropdown ul class=dropdo...

    用户5760343
  • bootstrap bootstrap-dropdown.js

    <ul class="nav nav-tabs"> <li class="active"><a href="#">Home</a></li> <li><a ...

    用户5760343
  • js事件对象相关随记

    天天_哥
  • 原 each()、map()

    作者:汪娇娇 日期:2016.9.1 如果说到某个元素的开关事件,第一反应那就是用一个变量做标记,比如flag,为1时开,为0时关,这是很简单的。下面我将以li...

    jojo
  • 马牌轮胎推出微信小程 优化整合服务渠道打造全新个性化解决方案

    近日,全球领先的轮胎制造商德国马牌轮胎宣布,于9月初正式上线微信小程序购胎平台,打造全新个性化购胎平台及轮胎解决方案,进一步优化整合线上线下服务渠道。据悉,德国...

    微信小程序开发加盟服务商

作者介绍

lonelydawn

上海软科教育信息咨询有限公司前端开发工程师

上海软科教育信息咨询有限公司 · 前端开发工程师 (已认证)

精选专题

活动推荐

扫码关注云+社区

领取腾讯云代金券