PDO 预处理|学习笔记

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 快速学习 PDO 预处理,本节学习PDO的预处理。与事务相同并不是PDO的功能,本节介绍PDO如何实现预处理。

开发者学堂课程【PHP 进阶教程-由浅入深掌握面向对象开发-第三阶段PDO 预处理】学习笔记,与课程紧密联系,让用户快速学习知识。  

课程地址:https://developer.aliyun.com/learning/course/713/detail/12737


PDO 预处理

 

内容介绍:

一、介绍

二、示例

三、小结

 

一、介绍:

1、目标:掌握PDO对于MySQL预处理的支持,能够利用PDO实现预处理操作

2、概念:

PDO预处理:是PDO针对MySQL预处理而封装一套特定的方法,在方法中做了一些优化操作,使得开发人员可以便捷的用来实现预处理

(1)PDO预处理的实现是基于MySQL预处理机制,只是针对预处理的操作过程进行了内部封装(与事务处理相同:内部再做封装,写好固定SQL指令)

参数处理:可以使用原占位符?,也可以使用PDO占位符:名字

例如在数据库中输入

prepare t_40_select from ‘select * from t_40 where id=?’

使用此类方式进行操作。而PDO可以使用占位符:名字做处理。’?’表达意思不明确,不能清楚具体代表;而名字表达清晰。在系统内部实际是将名字替换为?,使得用户操作方便。

(2)PDO中预处理提供了一套方法机制,主要由以下几个方法组成

PDO::prepare():发送预处理指令,只需要提供要执行的指令即可(然后会发送给服务器处理),不需要prepare名字from(名字为指定的)。成功得到一个PDOStatement类对象,失败得到一个false (或者异常错误)

PDOStatement:bindParam():绑定预处理所需要的参数,只能绑定变量(引用传递:传递数据时使用引用传递,所以只能传变量)

PDOStatement::bindValue():绑定预处理所需要的参数,可以绑定值(值传递:传递的为具体的一个值)

PDOStatement::execute():执行预处理(不需要再提供名字,系统自动检测执行),成功返回true,失败返回false

 

二、示例

1、PDO发送预处理指令∶即利用PDO:prepare()方法将要执行的SQL指令先发送给服务器编译

#实例化PDO对象

$drivers = array(

PDO ::ATTR_ERRMODE => PDO ::ERRMODE_EXCEPTION

); //此处用到异常处理模式,仅作了解

$pdo = new PDO( 'mysql:host=localhost;port=3306; dbname=db_2 ' , ' root ' , ' root ' , $drivers);

#发送预处理指令

$pre_sql = "select * from t_40";   #无数据预处理指令

$pre_sql = "select * from t_40 where id = ?";#有参数预处理指令

$pre_sql = "select * from t_40 where id =:id";# PDO特定预处理参数指令(:+字符串),更明确

#执行最后一条预处理指令:即使用:id作为参数的

$stmt = $pdo->prepare($pre_sql);

if( !$stmt) die('预处理指令执行失败! ');

演示预处理的执行:

创建文件36prepare.php

编写代码:

<?php

#PDO实现预处理

#实例化

$pdo = new PDO( 'mysql:host=localhost;port=3306;dbname=db_2;charset=utf8' , ' root' , 'root ' ) or die('数据库连接失败!'); //可以添加上字符集,加上连接

#准备预处理指令:发送给服务器

$pre_sql = "select * from t_40";    #无数据预处理指令

$pre_sql = "select * from t_40 where id = ?";#有参数预处理指令

$pre_sql = "select * from t_40 where id =:id";# PDO特定预处理参数指令(:+字符串),更明确

#发送预处理指令(例如现在使用第三条指令)

$stmt = $pdo->prepare($pre_sql);

if(!$stmt) die (‘预处理指令执行失败!’);   //成功继续向下执行,失败则die

访问网址36.prepare.php结果未显示任何内容。说明此处获取到的为false,查看false,继续输入代码:

var_dump($stmt);

再次刷新页面结果显示:

object(PDOStatement)#2 (1)( [ “queryString”]=> string(32) “select * from t _40 whereid = :id" )

结果得到的为一个对象。服务器这条指令并未执行,只是编译所以并不知哪种错误。

以上就拿到了对象,接着绑定参数,删掉var_dump($stmt);

2、绑定预处理参数:如果预处理本身是需要携带参数的,那么可以使用PDOStatement::bindvalue()/bindParam()进行参数绑定

l PDOStatement::bandValue()

#接上述代码

$stmt->bindValue( ' :id',1);#直接绑定数值

$id = 2;

$stmt->bindValue( ' :id ' , $id);#绑定变量数据

注意:如果在发送预处理指令的时候,使用的是"?"作为占位符,那么我们在进行绑定数据的时候,是按照顺序进行绑定的,起始位置的占位符序号为1,如果有多个占位符,依次类推

#预处理指令: select * from t_40 where id = ?

$stmt->bindValue(1,$id);

l PDOStatement::bindParam()

#接预处理指令

#$stmt->bindParam( ' : id',3);#错误:不能绑定值,引用传递,只能是变量

$id = 4;

$stmt->bindParam(' :id ' , $id);#必须是传递变量

演示:

继续在代码中添加:

#绑定预处理参数:bindValue

$stmt->bindValue( ' :id',1);#直接绑定数值

$id = 2;

$stmt->bindValue( ' :id ' , $id);#绑定变量数据

刷新页面无内容显示

#绑定预处理参数:bindParam

$stmt->bindParam( ' :id',1);  #错误:bindParam第二个参数要求必须为变量(引用传递)

bindParam不能绑定值,若绑定值则会出现如下错误:

image.png出现语法错误,提示Param第二个参数只能为引用。所以不能绑定数据,注释掉$stmt->bindParam( ' :id',1);

输入正确操作:

$id = 4;

$stmt->bindParam(' :id ' , $id);#必须是传递变量

刷新页面无显示结果

绑定完成后下一步为执行:

3、执行预处理:利用PROStatement::execute()方法

#接上述代码

$res = $stmt->execute();

if( !$res) die('预处理执行失败! ');

#如果是查询,想要得到预处理执行的结果,还需要使用PDOStatement::fetch()方法进行数据解析

$row = $stmt->fetch(PDO : : FETCH_ASSOC) ;

演示:

添加代码:

#执行预处理

$res = $stmt->execute();

var_dump($res);

刷新页面结果显示:   bool(false)

结果拿到false说明执行失败,预处理存在问题,因为上述的预处理指令$pre_sql = "select * from t_40 whereid =:id"是错误的,想要正确指令,进行修改$pre_sql = "select * from t_40 where id =:id"。结果显示bool(true)

#如果结果为true,说明预处理执行了,但是结果无法取出

#如果是查询预处理,需要继续进行PDOStatement::fetch()才能查出结果

输入代码:$row = $stmt->fetch(PDO : : FETCH_ASSOC) ;

var_dump($row);

刷新页面拿到结果。

#如果错误:取出信息

if($row===false){

#取出错误细信息:实际开发是将错误信息记录到系统日志中,返回false

echo 'SQL错误:<br/>' ;

echo '错误代码为:' . $stmt->errorCode() . '<br/> ';

echo’错误原因为:' . $stmt->errorInfo()[2];

exit;

}

刷新页面结果显示:

SQL错误:

错误代码为: 00000

错误原因为:You have an error in your SQl syntax, check the manual that coresponds to your MySQL sever version for the right syntax to use near' =’4" at line 1

以上提供的方法检查错误主要检查预处理后续执行错误,因为在前面预处理指令发送时这种指令并不会执行,所以SQL中有语法错误系统不能检测。只能等到执行预处理时才能执行指令。

例如:

image.png图上SQL有语法问题,prepare不能判定,只能输入execute t_40_select;此处没办法执行,还需要定义变量。过程如此。

MySQL中出现预处理执行错误,PDO会将其放到PDOStatement类中进行查询,通过errorInfo方法获取具体信息。

以上就为预处理,从定义到绑定指令,绑定完成后再进行执行,本质都十分清晰。例如bandValue是将?进行替换,替换成id,如果多个可以进行传递数组。如果为:id,系统找到:id替换为对应id值即可。做替换即完成数据操作,实际上是解析变量然后使用set变量,例如:set @id = 1;

execute t_40_select using @id;

结果如下:

image.png本质就是设置了一个变量再进行最终的execute时将设置的名字放在using中。名字与变量名不需考虑,只需绑定数据即可,内部自身组装。

 

三、小结

1、PDO预处理除了本身实现了MySQL的预处理,还额外优化了占位符:使用:+名字作为占位符(查看更清晰)

2、PDO利用了PDO::prepare()方法发送预处理SQL指令,成功得到PDOStatement对象

3、PDO利用PDOStatement::bindValue()/bindParam()来实现预处理数据绑定

4、PDO利用PDOStatement::execute()来实现调用预处理

5、如果利用PDO预处理来实现数据查询,那么在执行完成预处理之后,还需要调用PDOStatement::fetch()方法获取预处理得到的数据(所以查询预处理较少)

有了预处理后操作比较安全,数据是后期进行绑定,所以SQL注入可以实现避免。在批量处理时预处理也高效安全,但这些与PDO的预处理并无关系,而是MySQL预处理本身的特点。

PDO只是做外部的封装并没有改变预处理本身逻辑,由MySQL系统决定。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
测试技术
读完这篇文章后,才发现Allpairs这款工具,让测试用例变得如此简单
读完这篇文章后,才发现Allpairs这款工具,让测试用例变得如此简单
691 0
|
存储 供应链 安全
【区块链】智能交易模式下的数据安全流通模型
【区块链】智能交易模式下的数据安全流通模型
568 1
|
2月前
|
人工智能 测试技术 数据库
企业数字化如何避免智能体设计陷入‘技术堆砌’的陷阱,真正做到以业务为导向?
本文AI产品专家三桥君探讨了如何以业务为导向设计智能体系统,避免陷入技术堆砌陷阱。通过电信运营商套餐推荐场景,提出从需求分析、多智能体协同设计到开发落地的完整方法论。三桥君强调技术需服务于业务本质,为AI智能体落地提供系统性实践路径。
108 0
|
前端开发 JavaScript Python
【Django】Django4.1.2使用xadmin避坑指南(二)
【Django】Django4.1.2使用xadmin避坑指南(二)
|
12月前
|
SQL 关系型数据库 数据库连接
php连接数据库之PDO,PDO的简单使用和预定义占位符的使用以及PDOStatement对象的使用,占位符的不同形式,bindValue和bindParam绑定预定义占位符参数的区别
本文介绍了PHP中PDO(PHP Data Objects)扩展的基本概念和使用方法。内容包括PDO类和PDOStatement类的介绍,PDO的简单使用,预定义占位符的使用方法,以及PDOStatement对象的使用。文章还讨论了绑定预定义占位符参数的不同形式,即bindValue和bindParam的区别。通过具体示例,展示了如何使用PDO进行数据库连接、数据查询、数据插入等操作。
php连接数据库之PDO,PDO的简单使用和预定义占位符的使用以及PDOStatement对象的使用,占位符的不同形式,bindValue和bindParam绑定预定义占位符参数的区别
|
12月前
|
存储 NoSQL Java
aspect实现mock-feign接口
该代码为一个用于Feign接口的模拟(Mock)实现类`FeignMockAspect`,通过切面编程方式对带有`@FeignClient`注解的接口提供模拟响应。在非生产环境中,根据特定配置从Redis中获取Mock数据并转换为对应类型的对象返回,以减少对外部系统的依赖和提高测试效率。使用Hutool工具类和Spring Data Redis进行数据处理与存储操作。
|
11月前
|
数据采集 安全 API
数据治理:实现原始数据不出域,确保数据可用不可见的创新策略
在数字化时代,数据成为企业宝贵资产,驱动业务决策与创新。然而,数据量激增和流通频繁带来了安全和管理挑战。“原始数据不出域,数据可用不可见”的治理理念应运而生,通过数据脱敏、沙箱技术和安全多方计算等手段,确保数据安全共享与高效利用。这一理念已广泛应用于金融、医疗等行业,提升了数据价值和企业竞争力。
1712 0
|
人工智能 监控 决策智能
震惊!多角色 Agent 携手合作,竟能如此高效搞定复杂任务,背后秘密大揭晓!
在复杂任务环境中,单个智能体常因能力与资源限制而难以应对。多智能体系统(multi-agent systems)通过将任务分解并分配给各具专长的智能体,实现了高效协同工作。例如,在物流配送中,不同智能体分别处理路线规划、货物装载与交通监控,确保任务准确高效完成。同样,在大型游戏开发项目里,各智能体专注剧情设计、美术创作等特定领域,显著提升项目质量和开发速度。通过共享信息、协商决策等方式,多智能体系统展现出强大灵活性与适应性,为物流、软件开发等领域带来新机遇。
457 2
|
开发框架 前端开发 JavaScript
基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转
基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转
|
域名解析 缓存 负载均衡
你还别不信,大把网工还不懂:全局负载均衡与 CDN 内容分发!
你还别不信,大把网工还不懂:全局负载均衡与 CDN 内容分发!
351 0