PDO常用方法详解

PDO 是一个“数据库访问抽象层”,作用是统一各种数据库(MySQL、MSSQL、Oracle、DB2、PostgreSQL……)的访问接口,能轻松的在不同的数据库之间完成切换,使得数据库间的移植容易实现。
开启PDO
在pho.ini中查找php_pdo_yourssqlserverhere.extis把注释去掉就行了,很多集成环境默认是开启的。
可以用class_exitsts(“PDO”); 等方法调试是否开启

PDO对象建立

$dsn = 'mysql:host=localhost;dbname=my_db;port=3306'; //数据源:host主机名称、dbname数据库名称、port:数据库端口
$username = 'root'; //数据库用户名
$password = 'root'; //数据库密码

$pdo = new PDO($dsn, $username, $password);

转义用户输入(的特殊字符)

你可曾听说过(mysqli_)real_escape_string,这是用于确保用户输入安全数据。PDO提供了一个方法叫做quote,这个方法可以把输入字符串中带有引号的地方进行特殊字符转义。

$pdo->quote($input);

预处理语句

尽管exec方法和查询在PHP中仍然被大量使用和支持,但是PHP官网上还是要求大家用预处理语句的方式来替代。为什么呢?主要是因为:它更安全。预处理语句不会直接在实际查询中插入参数,这就避免了许多潜在的SQL注入。

然而出于某种原因,PDO实际上并没有真正的使用预处理,它是在模拟预处理方式,在将语句传给SQL服务器之前会把参数数据插入到语句中,这使得某些系统容易受到SQL注入。

如果你的SQL服务器不真正的支持预处理,我们可以很容易的通过如下方式在PDO初始化时传参来修复这个问题:

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

接下来开始我们的第一个预处理语句吧:

$statement = $pdo->prepare('SELECT * FROM test WHERE id=? AND username=?');
$statement = $pdo->prepare('SELECT * FROM test WHERE id=:id AND username=:username');

正如你所见,有两种创建参数的方法,命名(id=:id)的与匿名的(id=?)(不可以同时出现在一个语句中)。然后你可以使用bindValue来敲进你的输入:

$statement->bindValue(1, $id);
$statement->bindValue(2, $username);

$statement->bindValue(':id', $id);
$statement->bindValue(':username', $username);

注意使用命名参数的时候你要包含进冒号(:)。PDO还有一个bindParam方法,可以通过引用绑定数值,也就是说它只在语句执行的时候查找相应数值。
bindParam()bindValue() 非常相似。
唯一的区别就是前者使用一个PHP变量绑定参数,而后者使用一个值。
所以使用bindParam是第二个参数只能用变量名,而不能用变量值,而bindValue至可以使用具体值。

$stm = $pdo->prepare("select * from users where user = :user");  
$user = "jack";  
//正确  
$stm->bindParam(":user",$user);  
//错误  
//$stm->bindParam(":user","jack");  
//正确  
$stm->bindValue(":user",$user);  
//正确  
$stm->bindValue(":user","jack");  

另外在存储过程中,bindParam可以绑定为input/output变量,如下面

$stm = $pdo->prepare("call func(:param1)");  
$param1 = "abcd";  
$stm->bindParam(":param1",$param1); //正确  
$stm->execute(); 

存储过程执行过后的结果可以直接反应到变量上。
对于那些内存中的大数据块参数,处于性能的考虑,应优先使用前者。

为了避免只使用bindValue带来的代码碎片,你可以用数组给execute方法作为参数,像这样:

$statement->execute(array(1=>$id, 2=>$username));
$statement->execute(array(':id'=>$id, ':username'=>$username));

绑定值到变量 详情看官方文档http://php.net/manual/zh/pdostatement.bindcolumn.php
绑定结果集中的列到PHP变量是一种使每行包含的数据在应用程序中立即可用的有效方法。下面的例子演示了 PDO 怎样用多种选项和缺省值绑定和检索列。

<?php
function readData($dbh) {
  $sql = 'SELECT name, colour, calories FROM fruit';
  try {
    $stmt = $dbh->prepare($sql);
    $stmt->execute();

    /*  通过列号绑定  */
    $stmt->bindColumn(1, $name);
    $stmt->bindColumn(2, $colour);

    /*  通过列名绑定  */
    $stmt->bindColumn('calories', $cals);

    while ($row = $stmt->fetch(PDO::FETCH_BOUND)) {
      $data = $name . "\t" . $colour . "\t" . $cals . "\n";
      print $data;
    }
  }
  catch (PDOException $e) {
    print $e->getMessage();
  }
}
readData($dbh);
?>

事务

一个事务就是执行一组查询,但是并不保存他们的影响到数据库中。这样做的好处是如果你执行了4条相互依赖的插入语句,当有一条失败后,你可以回滚使得其他的数据不能够插入到数据库中,确保相互依赖的字段能够正确的插入。你需要确保你使用的数据库引擎支持事务。
开启事务

你可以很简单的使用beginTransaction()方法开启一个事务:

$pdo->beginTransaction();

$pdo->inTransaction(); // true!
$pdo->query('SELECT * .....');
.......
$

然后你可以继续执行你的数据库操作语句,在最后提交事务:

$db->commit();

还有类似MySQLi中的rollBack()方法,但是它并不是回滚所有的类型(例如在MySQL中使用DROP TABLE),这个方法并不是真正的可靠,我建议尽量避免依赖此方法。

其他有用的选项

有几个选项你可以考虑用一下。这些可以作为你的对象初始化时候的第四个参数输入。

$options = array($option1 => $value1, $option[..]);
$db = new PDO($dsn, $username, $password, $options);

PDO::ATTR_DEFAULT_FETCH_MODE

你可以选择PDO将返回的是什么类型的结果集,如PDO::FETCH_ASSOC,会允许你使用 result[columnname]PDO::FETCHOBJ便使 result->column_name

你还可以将结果放入一个特定的类(模型),可以通过给每一个单独的查询设置一个读取模式,就像这样:

$query = $db->query(‘SELECT * FROM `foods`‘);
$foods = $query->fetchAll(PDO::FETCH_CLASS, ‘Food‘);
PDO::ATTR_ERRMODE
  • 所有读取模式
    上面我们已经解释过这一条了,但喜欢TryCatch的人需要用到:PDO::ERRMODE_EXCEPTION。如果不论什么原因你想抛出PHP警告,就使用PDO::ERRMODE_WARNING。

PDO::ATTR_TIMEOUT

当你为载入时间而着急时,你可以使用此属性来为你的查询指定一个超时时间,单位是秒. 注意,如果超过你设置的时间,缺省会抛出E_WARNING异常, 除非 PDO::ATTR_ERRMODE 被改变.

更多属性信息可以在 PHP官网的属性设置 里查看到.
最后的思考

PDO是一个在PHP中访问你的数据库的很棒的方式,可以认为是最好的方式。除非你拒绝使用面向对象的方法或是太习惯 MySQLi 的方法名称,否则没有理由不使用PDO。

更好的是完全切换到只使用预处理语句,这最终将使你的生活更轻松!

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(),返回由对象组成的二维数组

fetchAll实例

$sql = 'SELECT * FROM test WHERE id=?';
$stmt = $pdo->prepare($sql);
$stmt->execute(array(1=>$id));
foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $row){
    echo $row['username'].$row['password'];
}

fetch实例

$sql = 'SELECT * FROM test WHERE id=?';
$stmt = $pdo->prepare($sql);
$stmt->execute(array(1=>$id));
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    echo $row['username'].$row['password'];
}

fetch每执行一次记录都往下移动一次,所以用while循环遍历结果集。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值