PHP之PDO扩展技术总结
执行sql语句: exec() 、query()、 perpare();
1、query用来处理有结果集的,如select, 返回 PDOStatement 对象,失败返回false(当为 PDO::ERRMODE_SILENT,这也是默认的值)
2、exec用来处理有返回影响行数的(int),如 insert(插入的行数)、 delete(删除的行数) 、update(和原数值不等才算), 失败返回false (当为 PDO::ERRMODE_SILENT,这也是默认的值)3、prepare 执行所有sql,可以完全替代 query,exec的功能
错误报告是针对执行的sql出错时
PDO::ERRMODE_SILENT(0) :默认 不提示任何错误 ,连接时无论如何都会提示,只有在执行后面的方法时才会起作用
PDO::ERRMODE_WARNING(1) : 警告
PDO::ERRMODE_EXCEPTION(2):异常(推荐使用) 用try catch捕获,也可以手动抛出异常 new PDOException($message, $code, $previous)
一 PDO基本认识
什么事PDO
POD(PHP Data Object)扩展在PHP5中加入,PHP6中将默认识用PDO连接数据库,所有非PDO扩展将会在PHP6被从扩展中移除。该扩展提供PHP内置类 PDO来对数据库进行访问,不同数据库使用相同的方法名,解决数据库连接不统一的问题。
如何开启PDO扩展
① 找到php目录下的php.ini配置文件
② 开启pdo_mysql.dll扩展(按需加载)
;开启php_pdo_mysql数据对象扩展
extension=php_pdo_mysql.dll
③ 重启Apache软件
④使用phpinfo函数判断pdo_mysql是否开启成功
二 、 PDO::__construct 创建一个表示数据库连接的 PDO (实例的对象)
PDO::__construct() ( string $dsn [, string $username [, string $password ]] )
$dsn :数据源 ,字符串类型 ,格式:mysql:host=localhost;dbname=project
$username :用户名,连接数据库的用户名
$password :密码,连接数据库的密码
<?php
/*如果试图连接到请求的数据库失败,则PDO::__construct() 抛出一个 PDO异常(PDOException)*/
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser'; //数据库用户名
$password = 'dbpass'; //数据库密码
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
?>
三、PDO::exec 执行一条 SQL 语句,并返回受影响的行数(数据的增删改)
int PDO::exec ( string $statement )
PDO::exec() 在一个单独的函数调用中执行一条 SQL 语句,返回受此语句影响的行数。
PDO::exec() 不会从一条 SELECT 语句中返回结果。对于在程序中只需要发出一次的 SELECT 语句,可以考虑使用 PDO::query()。对于需要发出多次的语句,可用 PDO::prepare() 来准备一个 PDOStatement 对象并用 PDOStatement::execute() 发出语句。
此函数可能返回布尔值 FALSE,但也可能返回等同于 FALSE 的非布尔值(没有受影响的行,则 PDO::exec() 返回 0,判断是布尔值false还是0时可以用 !== 或者 === 进行全比较)。
<?php $dbh = new PDO('odbc:sample', 'db2inst1', 'ibmdb2'); /* 删除 FRUIT 数据表中满足条件的所有行 */ $count = $dbh->exec("DELETE FROM fruit WHERE colour = 'red'"); /* 返回被删除的行数 */ print("Deleted $count rows.\n"); ?> 以上例程会输出: Deleted 1 rows.
四、PDO::query 执行一条SQL语句,返回一个结果集作为PDOStatement对象
<?php header("content-type:text/html;charset=utf-8"); $params = array ( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' , PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, ); $pdo = new PDO('mysql:host=127.0.0.1;dbname=bbs;port=3306', 'root', 'root',$params); $statement = "select * from user"; $stmt = $pdo->query($statement); echo "<pre>"; var_dump($stmt); /* 以下是输出的结果,可以看出返回一个结果集作为PDOStatement对象 object(PDOStatement)#2 (1) { ["queryString"]=> string(18) "select * from user" } */ ?>
注意:
1、query和exec都可以执行所有的sql语句,只是返回值不同而已。
2、query可以实现所有exec的功能。
3、当把select语句应用到 exec 时,总是返回 0
五、PDO中的遍历操作
要使用到的知识点:
- mixed PDOStatement::fetch (int $fetch_style) :实现对数据的遍历输出,每次只能遍历一条记录,然后指针向下移动一位!
参数说明:
PDO::FETCH_ASSOC :把一条记录遍历到关联数组中
PDO::FETCH_NUM :把一条记录遍历到索引型数组中
PDO::FETCH_BOTH :把一条记录遍历到混合型数组中
PDO::FETCH_OBJ :把一条记录遍历到对象中
PDO::FETCH_BOUND (bindColumn) :把某个变量绑定到结果集中的某个列
示例代码:PDO::FETCH_ASSOC
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; $pdo = new PDO($dsn, $user, $pass); //3、组装SQL语句 $sql = "select * from tb_admin"; //4、执行SQL语句 $stmt = $pdo->query($sql); //5、获取总记录数 $count = $stmt->rowCount(); //6、遍历数据到关联数组中 for($i=0;$i<$count;$i++) { //把一条记录遍历到关联型数组中 $row = $stmt->fetch(PDO::FETCH_ASSOC); var_dump($row); } ?>
示例代码:PDO::FETCH_BOUND(bindColumn)
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; $pdo = new PDO($dsn, $user, $pass); //3、组装SQL语句 $sql = "select * from tb_admin"; //4、执行SQL语句 $stmt = $pdo->query($sql); $count = $stmt->rowCount(); //5、使用bindColumn实现列绑定 $stmt->bindColumn(1,$id); //把变量$id绑定到结果集中的第1列 $stmt->bindColumn(2,$username); //把变量$username绑定到结果集中的第2列 $stmt->bindColumn(3,$password); //把变量$password绑定到结果集中的第3列 //6、使用for循环实现对结果集的遍历 for($i=0;$i<$count;$i++) { //指定fetch的绑定方式为PDO::FETCH_BOUND,否则bindColumn不会生效 $stmt->fetch(PDO::FETCH_BOUND); //输出$id/$username以及$password的基本信息 echo $id; echo '-'; echo $username; echo '-'; echo $password; echo '<hr />'; } ?>
要用到的知识点:
- array PDOStatement::fetchAll()
主要功能:把数据表中的记录返回到一个二维数组中
示例代码:
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; $pdo = new PDO($dsn, $user, $pass); //3、组装SQL语句 $sql = "select * from tb_admin"; //4、执行SQL语句 $stmt = $pdo->query($sql); //5、把数据表中的所有记录返回到一个二维数组中 $data = $stmt->fetchAll(PDO::FETCH_ASSOC); //6、遍历结果集 foreach($data as $row) { echo $row['id']; echo '-'; echo $row['username']; echo '-'; echo $row['password']; echo '<hr />'; } ?>
要用到的知识点:
- string PDOStatement::fetchColumn ([ int $column_number = 0 ] )
主要功能:遍历结果集当前行的某一列信息
参数说明:
$column_number :第几列,从0开始
示例代码:
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; $pdo = new PDO($dsn, $user, $pass); //3、组装SQL语句 $sql = "select * from tb_admin"; //4、执行SQL语句 $stmt = $pdo->query($sql); //5、获取总记录数 $count = $stmt->rowCount(); //6、使用for循环遍历结果集 for($i=0;$i<$count;$i++) { $id = $stmt->fetchColumn(0); echo $id.'<hr />'; } ?>
六、PDO扩展中的预处理功能
- PDO::prepare ( string $statement) :定义预处理语句 返回值为PDOStatement对象或者为false
- PDOStatement::execute ([ array $input_parameters ] ) :执行预处理语句 返回值为布尔值
- PDOStatement::bindParam ( mixed $parameter , mixed &$variable) 实现参数绑定
返回值为布尔值
$parameter :要绑定的参数 $variable :要设置的参数值,按引用传递
特别注意:如果以上参数,使用的是?问号标识,其绑定时索引是从1开始的!
预处理功能就是在SQL语句结构与形式相同的情况下,只有参数不同所采用的一种数据处理机制,其极大的减少了带宽的浪费。
示例①使用文本标识
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; $pdo = new PDO($dsn, $user, $pass); //3、组装SQL语句 $sql = "insert into tb_admin values (null,:username,:password,:time)"; //4、定义预处理语句 $stmt = $pdo->prepare($sql); //5、使用execute实现参数的传递 $password = md5('123456'); $time = time(); $data = array( ':username'=>'zhangsan', ':password'=>$password, ':time'=>$time ); $stmt->execute($data); ?>
示例②使用问号标识
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; $pdo = new PDO($dsn, $user, $pass); //3、组装SQL语句 $sql = "insert into tb_admin values (null,?,?,?)"; //4、定义预处理语句 $stmt = $pdo->prepare($sql); //5、使用execute传递参数 $password = md5('123456'); $time = time(); $data = array( 0=>'lisi', 1=>$password, 2=>$time ); $stmt->execute($data); ?>
示例③使用文本标识时参数绑定
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; $pdo = new PDO($dsn, $user, $pass); //3、组装SQL语句 $sql = "insert into tb_admin values (null,:username,:password,:time)"; //4、定义预处理语句 $stmt = $pdo->prepare($sql); //5、绑定参数 $stmt->bindParam(':username',$username); $stmt->bindParam(':password',$password); $stmt->bindParam(':time',$time); //6、设置参数 $username = 'wangwu'; $password = md5('123456'); $time = time(); //7、执行预处理语句 $stmt->execute(); ?>
示例④使用?标识参数绑定时
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; $pdo = new PDO($dsn, $user, $pass); //3、组装SQL语句 $sql = "insert into tb_admin values (null,?,?,?)"; //4、定义预处理语句 $stmt = $pdo->prepare($sql); //5、使用bindParam实现参数绑定 $stmt->bindParam(1,$username); $stmt->bindParam(2,$password); $stmt->bindParam(3,$time); //6、设置参数 $username = 'zhaoliu'; $password = md5('123456'); $time = time(); //7、执行预处理语句 $stmt->execute(); $username = 'tianqi'; $password = md5('123456'); $time = time(); $stmt->execute(); ?>
七、PDO中事务处理
事务处理主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
在事务处理中,所有步骤(操作)要么都成功,要么都失败。如果所有步骤都成功,则认为事务处理成功。如果有一个步骤出现了问题,则认为事务处理失败。
① 开启事务 bool PDO::beginTransaction ( void )
② 提交事务 bool PDO::commit ( void )
③ 回滚事务 bool PDO::rollBack ( void )
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; $pdo = new PDO($dsn, $user, $pass); //3、开启事务处理 $pdo->beginTransaction(); //4、定义交易流程(两个步骤:扣钱与加钱) $flag = true; $sql = "update tb_bank set money = 2000 where id = 1"; $affected_rows = $pdo->exec($sql); if(!$affected_rows) { $flag = false; } $sql = "update tb_bank set money = 0.1 where id = 3"; $affected_rows = $pdo->exec($sql); if(!$affected_rows) { $flag = false; } //5、判断交易是否成功 if($flag) { //交易成功,提交事务 $pdo->commit(); } else { //交易失败,回滚事务 $pdo->rollback(); } ?>
八、PDO中的异常类
PHP 5 提供了一种新的面向对象的错误处理方法。
异常处理用于在指定的错误(异常)情况发生时改变脚本的正常流程。这种情况称为异常。
PDO中的异常捕获基本语法:
try { 存在潜在错误的代码; if(逻辑错误) { //手工输出异常 throw new PDOException(‘错误的文本信息’,’错误号’); } } catch(PDOException $e) { echo ‘错误号:’.$e->getCode(); echo ‘错误行号:’.$e->getLine(); echo ‘错误的文本信息:’.$e->getMessage(); }
示例代码
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、定义相关参数 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dsn = "$dbms:host=localhost;dbname=project"; //3、实例化pdo类 try { $pdo = new PDO($dsn,$user,$pass); //4、定义SQL语句 $time = time(); $sql = "insert into tb_admin values (null,abcd,'123456',$time)"; $flag = $pdo->exec($sql); //5、手工抛出异常 if($flag === false) { throw new PDOException('SQL语句错误',1000); } } catch(PDOException $e) { echo '错误号:'.$e->getCode().'<hr />'; echo '错误行:'.$e->getLine().'<hr />'; echo '错误信息:'.$e->getMessage(); } ?>
九、PDO中属性的获取与设置
1、属性的获取与设置
要用到的知识点:
设置 :set 获取 :get 属性 :attribute
bool PDO::setAttribute ( int $attribute , mixed $value ) :设置属性
mixed PDO::getAttribute ( int $attribute ) :获取属性
参数说明:
$attribute :要设置或获取的属性
$value :要设置的属性值
2、PDO中常用的属性
① PDO::ATTR_AUTOCOMMIT :自动提交,常用于事务处理(语句事务)
参数值:
1 :自动提交
0 :关闭自动提交
② PDO::ATTR_CASE :结果集大小写
参数值:
PDO::CASE_LOWER(2) :把结果集(字段名称)全部转化为小写
PDO::CASE_UPPER(1) :把结果集(字段名称)全部转化为大写
PDO::CASE_NATURAL(0) :正常返回
③ PDO::ATTR_PERSISTENT :长连接
名词解析:
短连接 :连接 à 发送SQL语句 à 执行SQL语句 à 关闭
长连接 :连接 à a发送SQL语句 à 执行SQL语句 à a发送SQL语句 à 执行SQL语句 …
示例代码
<?php //1、设置响应头信息 header('Content-type:text/html; charset=utf-8'); //2、实例化pdo类 $dbms = 'mysql'; $user = 'root'; $pass = 'mysql'; $dbname = 'project'; $dsn = "$dbms:host=localhost; dbname=$dbname"; //设置长连接 $data = array(PDO::ATTR_PERSISTENT=>true); $pdo = new PDO($dsn, $user, $pass, $data); //3、设置常用属性 $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0); //关闭自动提交 $pdo->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER); //结果集字段全部转化为小写 //4、获取常用属性值 echo '自动提交:'; var_dump($pdo->getAttribute(PDO::ATTR_AUTOCOMMIT)); echo '<hr />'; echo '结果集大小写:'; var_dump($pdo->getAttribute(PDO::ATTR_CASE)); echo '<hr />'; echo '长连接:'; var_dump($pdo->getAttribute(PDO::ATTR_PERSISTENT)); echo '<hr />'; ?>
十、总结
① PDO扩展技术
PDO的基本概念以及为什么需要PDO
② PDO类(增删改查)
增删改:$pdo->exec($sql) 返回受影响的行数
查询:$pdo->query($sql) 返回PDOStatement类,fetch方法、fetchAll方法、fetchColumn方法
③ PDO中的预处理
减少SQL语句的传递,只传递相关的参数,这样可以减少带宽的浪费
prepare stmt1 from ‘insert into tb_admin values (null,?,?,?)’;
设置参数
set @参数 = 参数的值;
执行预处理
execute stmt1 using @参数;
④ PDO中的事务处理
开启事务beginTransaction()
提交事务commit()
回滚事务rollback()
⑤ 异常类PDOException
try {
//存在潜在错误的语句
if(逻辑错误) {
//手工抛出异常
throw new PDOException(‘错误信息’,’错误号’);
}
} catch(PDOException $e) {
echo $e->getCode();
echo $e->getLine();
echo $e->getMessage();
}
⑥ 属性的设置与获取
setAttribute
getAttribute