php中sdo和pdo,PHP之PDO的理解和实践

概念

什么是PDO, 即PHP DATA OBJECT,是一种抽象的数据库接口, 其本身并不会有任何的数据库功能, 只是定义了一些数据操作的接口规范。

如果需要针对某个数据库的操作, 需要对应的数据库类型的PDO驱动。这样才能真正的操作数据库.

同时, PDO 是需要PHP的面向对象的支持

优点

那么PDO 有什么优点呢

灵活

PDO 提供的是一种抽象的接口定义, 每种实际的PDO驱动都要实现这套定义。

既然接口一样, 那我们再代码中就能通过很少的代价对数据库进行替换了。 实际的操作只是更改了数据库驱动

安全

通过使用PDO的预处理语句,我们可以直接将查询参数传递进来, 而无需担心sql注入的问题

快速

当需要执行多个相似的sql查询语句, 而仅仅是查询参数不同的操作时, 通过预处理语句, 可以避免数据库对查询语句的重复解析/编译/优化的过程, 从而提高运行速度

PDO 类说明

PDO 的实现有主要有两个类, 在此说明下

PDO 类

这个类主要用于保存用户的数据库连接, 并设置连接参数,操作事务

通过这个类的实例, 我们还可以获取一些当前使用的数据库驱动的参数

比如: 当前连接是否处于事务状态,当前使用的是哪种数据库驱动

通过这个类实例的prepare方法, 我们可以预处理要执行的sql语句,这个函数返回的结果实际上就是下面要说的另外一个类PDOStatement类的实例

此外, 这个类的实例也可以直接对数据库发起请求, 比如exec和query函数

PDOStatement 类

代表一条预处理语句,并在该语句被执行后代表一个相关的结果集。

这是官方的一个说明。太过简单

上面PDO类实例的prepare`query函数的返回结果, 实际上也是PDOStatement`的实例。

这个类的实例拥有对数据库请求结果的多种操作和设置, 特别是,为PDO连接预处理sql语句时,其拥有的快速安全的特性,很受推崇

实践

PDO 类实践

连接数据库

try{

$dbh = new PDO("mysql:host=localhost;dbname=test_db;charset=utf8","root","1");

}catch(PDOException $e){

die("Error: $e");

}

这里我们连接上数据库后创建了一个PDO的类实例$dbh

获取数据库驱动类型

var_dump($dbh->getAvailableDrivers());

可以看到输出是

array(1) {

[0]=>

string(5) "mysql"

}

执行query

var_dump($stm = $dbh->query("select id,title from article",PDO::FETCH_NAMED));

这里我们直接使用PDO的query函数,第二个参数控制返回结果集, 比如返回的是一个关联数组, 用字段名作key,用查询结果做value时用PDO::FETCH_NAMED参数, 或者要返回一个索引数组, 直接用偏移量做key时, 用PDO::FETCH_NUM参数

在这里, 我们可以通过var_dump得到$stm的结果实际上就是PDOStatement类的实例

输出如下

object(PDOStatement)#2 (1) {

["queryString"]=>

string(28) "select id,title from article"

}

结果处理部分参考PDOStatement类实践

预处理

当我们有多个相似的语句, 这些语句唯一的区别就是参数不同, 或者需要执行多次的语句, 这个时候我们就比较适合使用预处理语句了

预处理语句可以预先解析,编译,优化sql语句, 返回一个PDOStatement类实例, 再调用该实例的execute函数, 传递不同的参数就能得到不同的结果, 同时, 因为避免了多次解析编译优化的过程, 可以使得后面的query请求更快

$stm = $dbh->prepare("select id,title from article where cid = :cid");

至于其中的:cid,其实只是一个占位符, 后面通过调用PDOStatement的bindParam或bindValue方法就可以通过变量将参数传递进去, 这里的:cid是关键词占位符, 每个关键词不可重复

或者这里也可以是

$stm = $dbh->prepare("select id,title from article where cid = ?");

?也是一个占位符, 通过调用PDOStatement的bindParam或bindValue方法也能传递参数进去, 也可以通过在调用execute时传递一个索引数组,数组里面的元素与?占位符一一对应, 也能传递参数到sql的请求里

PDOStatement 类实践

在上面我们通过两种方式得到了这个类实例

PDO的query函数 和PDO的预处理函数prepare

我们先说对调用prepare后的这个类实例

bindParam

在prepare当我们使用占位符时,我们可以通过bindParam将关键字与某个变量关联起来, 然后调用execute, 就能得到传递了参数的查询结果

$cid = 6;

var_dump($stm = $dbh->prepare("select id,title from article where cid = :cid"));

$stm->bindParam(":cid",$cid);

$stm->execute();

注意这里的绑定是引用绑定, 如果后面我们继续如下

$cid = 5;

$stm->execute();

实际的查询将是直接传递新的cid参数而无须再次绑定

对使用?来说, 绑定的关系只是从关键词变成了偏移量,

$cid = 6;

var_dump($stm = $dbh->prepare("select id,title from article where cid = ?"));

$stm->bindParam(0,$cid);

$stm->execute();

bindValue

bindValue与bindParam其实很类似, 也是为占位符填充具体的参数,绑定的方式基本上也与bindParam一致,只要把bindParam换成bindValue即可

但其余bindParam有什么区别呢

bindParam是引用方式绑定的变量, 只要变量做了修改, 那么query传递的参数就发生了变化。bindParam的例子里有说明

而bindValue只是绑定具体的值, 而非引用方式, 所以query传递的参数一旦需要修改,就要重新bindValue,所以要注意这点

execute

在prepare并绑定好参数后, 我们就可以直接调用execute去执行query请求了

$stm->bindParam(":cid",$cid);

$stm->execute();

假如prepare的query 中用的是?占位符, 还可以直接使用execute传递一个数组, 数组元素与query中的?一一对应, 也是可以传递请求参数的

setFetchMode

设置返回结果的格式, 比如是返回关联数组(PDO::FETCH_NAMED)结果还是索引数组(PDO::FETCH_NUM)结果

$stm->setFetchMode(PDO::FETCH_NAMED);

fetch 系列函数

然后我们就可以通过fetch系列函数返回结果了

如:

$stm->fetchall();//返回所有查询结果

$stm->fetch();//从结果集的下一行返回结果

$stm->fetchColumn();//从结果集中的下一行返回单独的一列。

$stm->fetchObject();// 从结果集的下一行返回结果并以对象的方式返回

对PDO的query函数的执行结果就可以通过这些函数返回

closeCursor

关闭游标,使语句能再次被执行。

在有些数据库驱动中, 如果查询结果不被fetch 完, 后续的查询就不能继续执行, 所以再查询完成后, 我们要调用这个函数,防止这种问题发生

总结

以上一个完整的例子如下:

try{

$dbh = new PDO("mysql:host=localhost;dbname=test_db;charset=utf8","root","1");

}catch(PDOException $e){

die("Error: $e");

}

var_dump($dbh->getAvailableDrivers());

$cid = 6;

$stm = $dbh->prepare("select id,title from article where cid = :cid");

$stm->bindParam(":cid",$cid);

$stm->execute();

$stm->setFetchMode(PDO::FETCH_NAMED);

while($row = $stm->fetch()){

var_dump("hello");

var_dump($row);

}

$stm->closeCursor();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值