赞
踩
PDO有非常多的操作却是MySQL扩展库所不具备的:
1:PDO真正的以底层实现的统一接口数库操作接口,不管后端使用的是何种数据库,如果代码封装好了以后,应用层调用基本上差不多的,当后端数据库更换了以后,应用层代码基本不用修改.
2:PDO支持更高级的DB特性操作,如:存储过程的调度等,mysql原生库是不支持的.
3:PDO是PHP官方的PECL库,兼容性稳定性必然要高于MySQL Extension,可以直接使用 pecl upgrade pdo 命令升级.
4:PDO可以防止SQL注入,确保数据库更加安全(原理其实就是:PHP就是通过实现SQL模板和参数变量分两次发送给MySQL,由MYSQL完成变量的转义处理,既然变量和SQL模板是两次发送的,也就不存在SQL注入的问题了)
下面是pdo方sql注入的代码:(即pdo通过预处理防止sql注入)
<?php
$pdo = new PDO("mysql:host=192.168.0.1;dbname=test;charset=utf8","root");
$st = $pdo->prepare("select * from info where id =? and name = ?");
$id = 21;
$name = 'zhangsan';
$st->bindParam(1,$id);
$st->bindParam(2,$name);
$st->execute();
$st->fetchAll();
?>
预处理语句
使用语句预处理将帮助你免于SQL注入攻击。
一条预处理语句是一条预编译的 SQL 语句,它可以使用多次,每次只需将数据传至服务器。其额外优势在于可以对使用占位符的数据进行安全处理,防止SQL注入攻击。
下面是未进行预处理和进行预处理的两段代码:
1.未进行预处理的代码:
(占位符的使用:)
http://zhidao.baidu.com/question/1541430860923158627
6.安装配置及测试
在windows下进行有关pdo测试的时候,php.ini中的extension_dir的值要填为pdo*.dll的路径,否则无法运行pdo的相关程序。
; Directory in which the loadable extensions (modules) reside.
extension_dir = "E:\www\php5\ext"
下面是一段PDO使用的代码,可以看一下:
1 <?php 2 $host = 'localhost'; 3 $user = 'root'; 4 $password = 'develop'; 5 $dbname = '99game'; 6 7 $dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $password); 8 9 //======================================================= 10 //例子 1. Execute a prepared statement with named placeholders 11 /* Execute a prepared statement by binding PHP variables */ 12 $user_id = 1; 13 $email = 'caihf_73940@qq.com'; 14 $sth = $dbh->prepare('SELECT user_id,email,token FROM 99game_user 15 WHERE user_id = :user_id AND email = :email'); 16 $sth->bindParam(':user_id', $user_id, PDO::PARAM_INT); 17 $sth->bindParam(':email', $email, PDO::PARAM_STR, 30); 18 $sth->execute(); 19 $result = $sth->fetch(PDO::FETCH_ASSOC); 20 print_r($result); 21 print("<br />\n"); 22 23 //例子 2. Execute a prepared statement with question mark placeholders 24 /* Execute a prepared statement by binding PHP variables */ 25 $user_id = 2; 26 $email = 'caihuafeng1@gmail.com'; 27 $sth = $dbh->prepare('SELECT user_id,email,token FROM 99game_user 28 WHERE user_id = ? AND email = ?'); 29 $sth->bindParam(1, $user_id, PDO::PARAM_INT); 30 $sth->bindParam(2, $email, PDO::PARAM_STR, 30); 31 $sth->execute(); 32 $result = $sth->fetch(PDO::FETCH_ASSOC); 33 print_r($result); 34 print("<br />\n"); 35 36 print "<hr />\n"; 37 //======================================================= 38 39 //======================================================= 40 $sth = $dbh->prepare("SELECT user_id,email,token FROM 99game_user limit 10"); 41 $sth->execute(); 42 43 /* 运用 PDOStatement::fetch 风格 */ 44 print("PDO::FETCH_ASSOC: "); 45 print("Return next row as an array indexed by column name<br />\n"); 46 $result = $sth->fetch(PDO::FETCH_ASSOC); 47 print_r($result); 48 print("<br />\n"); 49 print("\n"); 50 51 print("PDO::FETCH_BOTH: "); 52 print("Return next row as an array indexed by both column name and number<br />\n"); 53 $result = $sth->fetch(PDO::FETCH_BOTH); 54 print_r($result); 55 print("<br />\n"); 56 print("\n"); 57 58 print("PDO::FETCH_LAZY: "); 59 print("Return next row as an anonymous object with column names as properties<br />\n"); 60 $result = $sth->fetch(PDO::FETCH_LAZY); 61 print_r($result); 62 print("<br />\n"); 63 print("\n"); 64 65 print("PDO::FETCH_OBJ: "); 66 print("Return next row as an anonymous object with column names as properties<br />\n"); 67 $result = $sth->fetch(PDO::FETCH_OBJ); 68 print_r($result); 69 print 'user_id:' . $result->user_id; 70 print("<br />\n"); 71 print("\n"); 72 73 print "<hr />\n"; 74 //======================================================= 75 76 //======================================================= 77 function readDataForwards($dbh) { 78 $sql = 'SELECT user_id,email,token FROM 99game_user limit 10'; 79 try { 80 $stmt = $dbh->prepare($sql, array(PDO::ATTR_CURSOR, PDO::CURSOR_SCROLL)); 81 $stmt->execute(); 82 while ($row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT)) { 83 $data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "<br />\n"; 84 print $data; 85 } 86 $stmt = null; 87 } 88 catch (PDOException $e) { 89 print $e->getMessage(); 90 } 91 } 92 93 function readDataBackwards($dbh) { 94 $sql = 'SELECT user_id,email,token FROM 99game_user limit 10'; 95 try { 96 $stmt = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL)); 97 $stmt->execute(); 98 $row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_LAST); 99 do { 100 $data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "<br />\n"; 101 print $data; 102 } while ($row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_PRIOR)); 103 $stmt = null; 104 } 105 catch (PDOException $e) { 106 print $e->getMessage(); 107 } 108 } 109 110 print "Reading forwards:<br />\n"; 111 readDataForwards($dbh); 112 113 print "<hr />\n"; 114 115 print "Reading backwards:<br />\n"; 116 //下面的数据没有按照想像中的倒排输出,暂时不知道什么原因,php.net官方手册中的例子也是这么写的 117 readDataBackwards($dbh); 118 //======================================================= 119 ?>
-
- <?php
- $dbh = new PDO('mysql:host=localhost;dbname=access_control', 'root', '');
- $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- $dbh->exec('set names utf8');
- /*添加*/
- //$sql = "INSERT INTO `user` SET `login`=:login AND `password`=:password";
- $sql = "INSERT INTO `user` (`login` ,`password`)VALUES (:login, :password)"; $stmt = $dbh->prepare($sql); $stmt->execute(array(':login'=>'kevin2',':password'=>''));
- echo $dbh->lastinsertid();
- /*修改*/
- $sql = "UPDATE `user` SET `password`=:password WHERE `user_id`=:userId";
- $stmt = $dbh->prepare($sql);
- $stmt->execute(array(':userId'=>'7', ':password'=>'4607e782c4d86fd5364d7e4508bb10d9'));
- echo $stmt->rowCount();
- /*删除*/
- $sql = "DELETE FROM `user` WHERE `login` LIKE 'kevin_'"; //kevin%
- $stmt = $dbh->prepare($sql);
- $stmt->execute();
- echo $stmt->rowCount();
- /*查询*/
- $login = 'kevin%';
- $sql = "SELECT * FROM `user` WHERE `login` LIKE :login";
- $stmt = $dbh->prepare($sql);
- $stmt->execute(array(':login'=>$login));
- while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
- print_r($row);
- }
- print_r( $stmt->fetchAll(PDO::FETCH_ASSOC));
- ?>
-
1 建立连接
-
- <?php
- $dbh=newPDO('mysql:host=localhost;port=3306; dbname=test',$user,$pass,array(
- PDO::ATTR_PERSISTENT=>true
- ));
- ?>
持久性链接PDO::ATTR_PERSISTENT=>true
2. 捕捉错误
-
- <?php
- try{
- $dbh=newPDO('mysql:host=localhost;dbname=test',$user,$pass);
-
- $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
-
- $dbh->exec("SET CHARACTER SET utf8");
- $dbh=null; //断开连接
- }catch(PDOException$e){
- print"Error!:".$e->getMessage()."<br/>";
- die();
- }
- ?>
-
3. 事务的
-
- <?php
- try{
- $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
-
- $dbh->beginTransaction();//开启事务
- $dbh->exec("insertintostaff(id,first,last)values(23,'Joe','Bloggs')");
- $dbh->exec("insertintosalarychange(id,amount,changedate)
- values(23,50000,NOW())");
- $dbh->commit();//提交事务
-
- }catch(Exception$e){
- $dbh->rollBack();//错误回滚
- echo"Failed:".$e->getMessage();
- }
- ?>
4. 错误处理
a. 静默模式(默认模式)
-
- $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_SILENT); //不显示错误
- $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);//显示警告错误,并继续执行
- $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);//产生致命错误,PDOException
-
- <?php
- try{
- $dbh = new PDO($dsn, $user, $password);
- $sql = 'Select * from city where CountryCode =:country';
- $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
- $stmt = $dbh->prepare($sql);
- $stmt->bindParam(':country', $country, PDO::PARAM_STR);
- $stmt->execute();
- while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
- print $row['Name'] . "/t";
- }
- } // if there is a problem we can handle it here
- catch (PDOException $e) {
- echo 'PDO Exception Caught. ';
- echo 'Error with the database: <br />';
- echo 'SQL Query: ', $sql;
- echo 'Error: ' . $e->getMessage();
- }
- ?>
1. 使用 query()
-
- <?php
- $dbh->query($sql); 当$sql 中变量可以用$dbh->quote($params); //转义字符串的数据
-
- $sql = 'Select * from city where CountryCode ='.$dbh->quote($country);
- foreach ($dbh->query($sql) as $row) {
- print $row['Name'] . "/t";
- print $row['CountryCode'] . "/t";
- print $row['Population'] . "/n";
- }
- ?>
-
2. 使用 prepare, bindParam和 execute [建议用,同时可以用添加、修改、删除]
-
- <?php
- $dbh->prepare($sql); 产生了个PDOStatement对象
-
- PDOStatement->bindParam()
-
- PDOStatement->execute();//可以在这里放绑定的相应变量
- ?>
-
3. 事物
-
- <?php
- try {
- $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', '');
- $dbh->query('set names utf8;');
- $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- $dbh->beginTransaction();
- $dbh->exec("Insert INTO `test`.`table` (`name` ,`age`)VALUES ('mick', 22);");
- $dbh->exec("Insert INTO `test`.`table` (`name` ,`age`)VALUES ('lily', 29);");
- $dbh->exec("Insert INTO `test`.`table` (`name` ,`age`)VALUES ('susan', 21);");
- $dbh->commit();
- } catch (Exception $e) {
- $dbh->rollBack();
- echo "Failed: " . $e->getMessage();
- }
- ?>
-
PDO常用方法:
PDO::query()主要用于有记录结果返回的操作(PDOStatement),特别是select操作。
PDO::exec()主要是针对没有结果集合返回的操作。如insert,update等操作。返回影响行数。
PDO::lastInsertId()返回上次插入操作最后一条ID,但要注意:如果用insert into tb(col1,col2) values(v1,v2),(v11,v22)..的方式一次插入多条记录,lastinsertid()返回的只是第一条(v1,v2)插入时的ID,而不是最后一条记录插入的记录ID。
PDOStatement::fetch()是用来获取一条记录。配合while来遍历。
PDOStatement::fetchAll()是获取所有记录集到一个中。
PDOStatement::fetchcolumn([int column_indexnum])用于直接访问列,参数column_indexnum是该列在行中的从0开始索引值,但是,这个方法一次只能取得同一行的一列,只要执行一次,就跳到下一行。因此,用于直接访问某一列时较好用,但要遍历多列就用不上。
PDOStatement::rowcount()适用于当用query("select ...")方法时,获取记录的条数。也可以用于预处理中。$stmt->rowcount();
PDOStatement::columncount()适用于当用query("select ...")方法时,获取记录的列数。
注解:
1、选fetch还是fetchall?
小记录集时,用fetchall效率高,减少从数据库检索次数,但对于大结果集,用fetchall则给系统带来很大负担。数据库要向WEB前端传输量太大反而效率低。
2、fetch()或fetchall()有几个参数:
-
- mixed pdostatement::fetch([int fetch_style [,int cursor_orientation [,int cursor_offset]]])
- array pdostatement::fetchAll(int fetch_style)
fetch_style参数:
■$row=$rs->fetchAll(PDO::FETCH_BOTH); FETCH_BOTH是默认的,可省,返回关联和索引。
■$row=$rs->fetchAll(PDO::FETCH_ASSOC); FETCH_ASSOC参数决定返回的只有关联数组。
■$row=$rs->fetchAll(PDO::FETCH_NUM); 返回索引数组
■$row=$rs->fetchAll(PDO::FETCH_OBJ); 如果fetch()则返回对象,如果是fetchall(),返回由对象组成的二维数组
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。