PDO概述
1、PDO简介
- PDO是PHP数据对象(PHP Data Object)的缩写。
- PDO扩展为PHP访问不同数据库定义了一个轻量级的、一致性的接口;
- PDO作用是统一各种数据库的访问接口,PDO让跨数据库的使用更具亲和力;
- 有了PDO,您不必再使用mysqli_*函数、oci_*函数或者mssql_*函数,也不必再为它们封装数据库操作类,只需要使用PDO接口中的方法就可以对各种数据库进行操作。
- PDO是一个第三方的类,默认已经集成到PHP中了。
2、PDO的访问流程图
extension=php_pdo_mysql.dll
3、创建PDO类的对象
- 描述:创建一个表示数据库连接的 PDO 对象。
语法:
PDO::__construct ( string $dsn [, string $username [, string $password [, array $driver_options ]]] )
参数:
$dsn,数据源名称或叫做 DSN,包含了请求连接到数据库的信息。通常,一个
DSN 由 PDO 驱动名、紧随其后的冒号、以及具体 PDO 驱动的连接语法组成。
- 例如:$dsn = “mysql : host=127.0.0.1; port=3306; dbname=db; charset=utf8”
- $username,数据库用户名。
- $password,数据库密码。
- 返回值:成功则返回一个PDO对象。
代码示例:
<?php
// 定义数据库配置信息
$dsn = "mysql:host=localhost;port=3306;dbname=imageSystem;charset=utf8"; // 参数可以改,变量名不要改!
$username = "imageSystem";
$password = "imageSystem";
// 创建一个PDO对象
$my_db = new PDO($dsn, $username, $password);
// 打印对象信息
var_dump($my_db); // object(PDO)#1 (0) { }
PDO对象常用方法
1、PDO::exec()方法
- 描述:执行一条 SQL 语句,并返回受影响的行数
- 语法:int PDO::exec ( string $sql )
- 参数:$sql要被预处理和执行的 SQL 语句。
- 注意:不会从SELECT语句返回结果。
- 返回:返回受修改或删除 SQL 语句影响的行数。如果没有受影响的行,则返回 0。
$sql = 'UPDATE photos SET viewsNum=viewsNum+1 WHERE id=1';
if ($my_db->exec($sql)) {
echo "数据库执行成功!";
} else {
echo "Error!";
}
2、PDO::query()方法
- 描述:执行一条SQL语句,返回一个结果集对象( PDOStatement )。
- 语法:public PDOStatement PDO::query ( string $statement )
- 提示:主要用于SELECT、SHOW语句。
- 返回:执行成功返回PDOstatement对象,执行失败返回FALSE。
$sql = 'SELECT * FROM photos';
$PDOStatement = $my_db->query($sql);
var_dump($PDOStatement); // object(PDOStatement)#2 (1) { ["queryString"]=> string(20) "SELECT * FROM photos" }
3、PDO::lastInsertId()方法
- 描述:返回最后插入行的ID或序列值
- 语法:string PDO::lastInsertId ( void )
- 返回:返回最后插入行的ID。
$sql = 'INSERT INTO photos( title, imgsrc, info, viewsNum, created) VALUES("测试", "./imageSystem/02判断文件内容类型.php", "这是一条测试信息", 9999, 1597740842)';
$my_db->exec($sql);
$last_id = $my_db->lastInsertId();
echo "数据库最后插入的ID为:" . $last_id; // 数据库最后插入的ID为:6
4、PDO::setAttribute()方法
- 描述:设置数据库句柄属性
语法:https://www.php.net/manual/zh/pdo.setattribute.php
PDO::setAttribute ( int $attribute , mixed $value ) : bool
提示:PDO内置了一些可用的通用属性(详细见手册)
- PDO::ATTR_CASE:强制列名为指定的大小写。
- PDO::ATTR_ERRMODE:错误报告
- PDO::ATTR_DEFAULT_FETCH_MODE: 设置默认的提取模式。
- 返回:成功时返回 TRUE, 或者在失败时返回 FALSE。
// 创建一个PDO对象
$my_db = new PDO($dsn, $username, $password);
/**
* 设置PDO返回结果集为枚举类型数据
* PDO::FETCH_ASSOC:返回一个索引为结果集列名的数组
* PDO::FETCH_BOTH(默认):返回一个索引为结果集列名和以0开始的列号的数组
* PDO::FETCH_BOUND:返回 TRUE ,并分配结果集中的列值给 PDOStatement::bindColumn() 方法绑定的 PHP 变量。
*/
$my_db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
PDOStatement对象常用方法
1、PDOStatement::fetch()方法
- 描述:从结果集中获取一行,并向下移动指针
- 语法:mixed PDOStatement::fetch ([ int $fetch_style ] )
参数:$fetch_style,控制下一行如何返回给调用者。
- PDO::FETCH_ASSOC,返回一个索引为结果集列名的数组
- PDO::FETCH_BOTH(默认),返回一个索引为结果集列名和以0开始的列号的数组
- PDO::FETCH_NUM:返回一个索引为以0开始的结果集列号的数组
- 返回:此函数(方法)成功时返回的值依赖于提取类型。在所有情况下,失败都返回FALSE 。
$sql = 'SELECT * FROM photos';
// 执行sql语句
$PDOstatement = $my_db->query($sql);
// 循环输出结果
while ($row = $PDOstatement->fetch()) {
print_r($row);
}
2、PDOStatement::fetchAll()方法
- 描述:返回一个包含结果集中所有行的数组
- 语法:array PDOStatement::fetchAll ([ int $fetch_style ] )
参数:$fetch_style,控制下一行如何返回给调用者。
- PDO::FETCH_ASSOC,返回一个索引为结果集列名的数组
- PDO::FETCH_BOTH(默认),返回一个索引的数组
- PDO::FETCH_NUM:返回一个索引为以0开始的结果集列号的数组
$sql = 'SELECT * FROM photos';
// 执行sql语句
$PDOstatement = $my_db->query($sql);
// 获取所有行
$rows = $PDOstatement->fetchAll();
print_r($rows); // 返回一个二维数组
3、PDOStatement::rowCount()方法
- 描述:返回受上一个 SQL 语句影响的行数
- 语法:int PDOStatement::rowCount ( void )
- 返回:返回上一个由对应的 PDOStatement 对象执行SELECT、DELETE、 INSERT、或 UPDATE 语句受影响的行数。
- 提示:要想使用该函数,必须使用 $pdo->query() 返回 PDOStatement 对象。
<?php
// 定义数据库配置信息
$dsn = "mysql:host=localhost;port=3306;dbname=imageSystem;charset=utf8";
$username = "imageSystem";
$password = "imageSystem";
// 创建一个PDO对象
$my_db = new PDO($dsn, $username, $password);
// 设置PDO返回结果集为枚举类型数据
$my_db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// 编写sql语句
// $sql = 'INSERT INTO photos( title, imgsrc, info, viewsNum, created) VALUES("测试", "./imageSystem/02判断文件内容类型.php", "这是一条测试信息", 9999, 1597740842)';
// $sql = 'SELECT * FROM photos';
$sql = "UPDATE photos SET viewsNum=viewsNum+1";
// 执行sql语句
$PDOstatement = $my_db->query($sql);
// 获取所有行
$rows_num = $PDOstatement->rowCount();
echo "本次sql语句影响行数为:{$rows_num}";
PDO错误处理
1、PDO支持三种错误模式
- 静默模式(Silent):错误发生后,不会主动报错,是默认的模式;
- 警告模式(Warning):错误发生后,通过PHP标准来报告错误;
- 异常模式(Exception):错误发生后,抛出异常,需要捕捉和处理;
- 提示:可以通过 PDO::setAttribute() 更改错误模式。
2、静默模式(Slient)
在静默模式下,当有错误发生时,不会显示在页面上;
此时,可以通过PDO的PDO::errorCode()和PDO::errorInfo()两个方法,来获取错误信息。
<?php
// 定义数据库配置信息
$dsn = "mysql:host=localhost;port=3306;dbname=imageSystem;charset=utf8";
$username = "imageSystem";
$password = "imageSystem";
// 创建一个PDO对象
$my_db = new PDO($dsn, $username, $password);
// 设置PDO返回结果集为枚举类型数据
$my_db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// 设置PDO错误显示类型
// $my_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
// 正确的sql语句
// $sql = "UPDATE photos SET viewsNum=viewsNum+1";
// 错误的sql语句
$sql = "UPDATE photos viewsNum=viewsNum+1";
// 执行sql语句
$PDOstatement = $my_db->query($sql);
// 获取所有行
// $rows_num = $PDOstatement->rowCount();
// echo "本次sql语句影响行数为:{$rows_num}";
echo "错误码为:".$my_db->errorCode(); // 错误码为:42000
echo "错误信息为:"; // 错误信息为:Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '=viewsNum+1' at line 1 )
print_r($my_db->errorInfo());
3、警告模式(Warning)
因为默认报错模式是静默模式(silent),如果想报警告错误,必须使用setAttribute()方法提前设置。
// 设置PDO错误显示类型
$my_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
// 错误的sql语句
$sql = "UPDATE photos viewsNum=viewsNum+1";
/**
* 错误信息:
* Warning: PDO::query(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '=viewsNum+1' at line 1 in C:\phpstudy_pro\WWW\a.com\demo.php on line 22
*/
4、异常模式(Exception)
因为默认报错模式是静默模式(silent),如果想报异常错误,必须使用setAttribute()方法提前设置。
// 设置PDO错误显示类型
$my_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 错误的sql语句
$sql = "UPDATE photos viewsNum=viewsNum+1";
/**
* 错误信息:
* Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '=viewsNum+1' at line 1 in C:\phpstudy_pro\WWW\a.com\demo.php:26 Stack trace: #0 C:\phpstudy_pro\WWW\a.com\demo.php(26): PDO->query('UPDATE photos v...') #1 {main} thrown in C:\phpstudy_pro\WWW\a.com\demo.php on line 26
*/
// 执行sql语句
$PDOstatement = $my_db->query($sql);
SQL语句预处理
1、SQL语句执行过程
- SQL语句的执行,分成两个阶段:编译和执行。
- 如果SQL语句,是第1次执行,先编译再执行。编译过程十分复杂,耗用系统资源,相对不太安全;
- 如果SQL语句(即相同的SQL语句),是第2次执行,直接从缓存中读取,无疑执行效率是最高的,也是比较安全的,可以有效避免SQL注入等安全问题;
2、PDO的SQL语句预处理步骤
(1)PDO完成预处理需要的步骤
- 先提取相同结构的sql部分!(将数据部分,可变的部分去掉)
- 编译这个相同的结构!将编译结果保存!
- 再将不同的数据部分进行替换!
- 执行即可!
(2)提取相同结构的SQL语句
- 在SQL语句中,使用命名参数和问号参数,来代替可变的数据。
- 使用占位符“:value”和“?”来代替可变的数据。
// 编写预编译的sql语句,$sql_01与$sql_02是一样的语句,只不过使用了不同的占位符.
$sql_01 = 'INSERT INTO photos( title, imgsrc, info, viewsNum, created) VALUES(:title, :imgsrc, :info, :viewsNum, :created)';
$sql_02 = 'INSERT INTO photos( title, imgsrc, info, viewsNum, created) VALUES(?, ?, ?, ?, ?)';
(3)预编译相同结构的SQL语句
- 描述:执行预编译的SQL语句结构,并返回一个PDOStatement对象。
- 语法:public PDOStatement PDO::prepare ( string $statement )
// 预编译sql语句 $PDOstatement = $my_db->prepare($sql_01); // 输出 print_r($PDOstatement); // PDOStatement Object ( [queryString] => INSERT INTO photos( title, imgsrc, info, viewsNum, created) VALUES(:title, :imgsrc, :info, :viewsNum, :created) )
(4)给占位符绑定数据
- 描述:绑定一个值到预处理的 SQL 语句中的对应命名占位符或问号占位符。
- 语法:bool PDOStatement::bindValue ( mixed $parameter , mixed $value )
参数:
$parameter,参数标识符。对于使用命名占位符的预处理语句,应是类似 :name
形式的参数名。对于使用问号占位符的预处理语句,应是以1开始索引的参数位置。
- $value,绑定到参数的值;
返回:成功时返回 TRUE, 或者在失败时返回 FALSE。
$PDOstatement->bindValue(1, '可爱女人');
$PDOstatement->bindValue(2, './imageSystem/02判断文件内容类型.php');
$PDOstatement->bindValue(3, '这是一个可爱的女人');
$PDOstatement->bindValue(4, 1234);
$PDOstatement->bindValue(5, time());
// 给字母占位符绑定值
$PDOstatement->bindValue('title', '可爱女人');
$PDOstatement->bindValue('imgsrc', './imageSystem/02判断文件内容类型.php');
$PDOstatement->bindValue('info', '这是一个可爱的女人');
$PDOstatement->bindValue('viewsNum', 1234);
$PDOstatement->bindValue('created', time());
#### (5)执行预处理的SQL语句
- 描述:执行一条预处理语句
- 语法:**bool PDOStatement::execute( )**