PHP PDO笔记
0x01:测试PDO是否安装成功
运行如下代码,如果提示参数错误,说明PDO已经安装,如果提示对象不存在,则修改PHP配置文件PHP.INI,取消php_pdo_yourssqlserverhere.extis前面的注释。
1 |
$test = new PDO(); |
0x02:连接数据库
运行Apache服务器,确定服务器已经运行并且PDO安装成功,那么下面我们就来连接数据库吧。
1 2 3 4 5 6 7 8 |
$dsn = 'mysql:dbname=demo;host=localhost;port=3306'; $username = "root"; $password = "password_here"; try{ $db = new PDO($dsn,$username,$password); }catch (PDOException $e) { die('Could not connect to the database:' . $e); } |
0x03:基本查询
在PDO中使用query和exec两种方法使得对数据库查询变得非常简单。如果你想得到查询结果的行数exec是非常好用的,因此对SELECT查询语句是非常有用的。
1 2 3 4 5 6 |
$statement = <<<SQL SELECT * FROM `foods` WHERE `healthy` = 0 SQL; $foods = $db->query($statement); |
如果上面的查询是正确的,则$foods现在是一个PDO Statement对象,我们可以从这个对象中获取我们需要的结果和一共查询到多少结果集。
0x04:获取行数
如果利用的是Mysql数据库,PDO Statement中包含了一个rowCount的方法可以获取结果集中的行数,如下代码所示:
1 |
echo $foods->rowCount; |
0x05:遍历结果集
PDO Statement可以使用foreach语句遍历,如下面代码所示:
1 2 3 |
foreach($foods->FetchAll() as $food){ echo $food['name'] . ' '; } |
PDO也支持Fetch方法,这个方法只返回一条结果。
0x06:转义用户输入的特殊字符
PDO提供了一个方法叫做quote,这个方法可以把输入字符串中带有引号的地方进行特殊字符转义。
1 2 3 |
$input = "this is's' a '''pretty dange'rous str'ing"; $db->quote($input); //使用quote方法转义后:'this is\'s\' a \'\'\'pretty dange\'rous str\'ing' |
0x07: exec()
PDO可以使用exec()方法实现UPDATE,DELETE和INSERT操作,招待后它会返回受影响行数的数量:
1 2 3 4 5 |
$statement = <<<SQL DELETE FROM `foods` WHERE `healthy` = 1; SQL; echo $db->exec($statement); |
0x08:预处理语句
尽管exec()方法和查询在PHP中仍然被大量使用和支持,但是PHP官网上还是要求大家用预处理语句方式来替代。为什么呢?主要是因为:它更安全。预处理语句不会直接在实际查询中插入参数,这就避免了许多潜在的SQL注入。
然而出于某种原因,PDO实际上并没有真正的使用预处理,它是在模拟预处理方式,在将语句传给SQL服务器之前会把参数数据插入到语句中,这使得某些系统容易 受到SQL注入。
如果你的SQL服务器不真正支持预处理,我们可以很容易的通过如下方式在PDO初始化时传参来修复这个问题:
1 |
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); |
下面是我们的第一个预处理语句:
1 2 |
$statement = $db->prepare('SELECT * FROM foods WHERE `name`=? AND `HEALTHY`=?'); $statement2 = $db->prepare('SELECT * FROM foods WHERE `name`=:name and `healthy`=:healthy'); |
如上面的代码所示,有两种创建参数的方法,全名的与匿名的(不可以同时出现在一个语句中)。然后你可以使用bindValue来敲进你的输入:
1 2 3 4 |
$statement->bindValue(1,'Cake'); $statement->bindValue(2,true); $statement2->bindValue(':name','Pie'); $statement2->bindValue(':healthy',false); |
注意使用命名参数的时候你要包含冒号( :)。PDO还有一个bindParam方法,可以通过引用绑定数值,也就是说它只在语句执行的时候查找相应数值。
现在剩下的唯一要做的事情,就是招待我们的语句:
1 2 3 4 5 |
$statement->execute(); $statement2->execute(); //获取我们的结果 : $cake = $statement->fetchAll(); $pie = $statement2->fetchAll(); |
为了避免只使用bindValue带来的代码碎片,你可以用数组给execute方法作为参数 ,像这样:
1 2 |
$statement->execute(array(1 => 'Cake', 2 => true)); $statement->execute(array(':name' => 'Pie', ':healthy' => false)); |
0x10开启事务
你可以很简单的使用beginTransaction()开启一个事务
1 2 |
$db->beginTransaction(); $db->inTransaction(); //true |
然后你可以继续提交你的数据库操作语句,在最后提交事务:
1 |
$db->commit(); |
还有类似MySQLi中的rollBack()方法,但是它并不是回滚所有的类型(例如在MySQL中使用DROPTABLE),这个方法并不是真正的可靠,建议尽量避免依赖些方法.
0x11:其它有用的选项
有几个选项你可以考虑用一下.这些可以作为你的对象初始化时候的第四个参数输入.
1 2 |
$options = array($option1 => $value1, $option[..]); $db = new PDO($dsn, $username, $password, $options); |
11.1. PDO::ATTR_DEFAULT_FETCH_MODE
你可以选择PDO将返回的是什么类型结果集,如PDO::FETCH_ASSOC,会允许你使用$result[‘column_name’],或PDO::FETCH_OBJ,会返回一个匿名对象,以便你使用$result->column_name
你还可以将结果放入一个特定的类(模型),可以通过给每一个单独的查询设置一个读取模式,就像这样:
1 2 |
$query = $db->query('SELECT * FROM `foods`'); $foods = $query->fetchAll(PDO::FETCH_CLASS,'Food'); |
11.2. PDO::ATTR_ERRMODE
上面我们已经解释过这一条了,但喜欢TryCatch的人需要用到:
PDO::ERRMODE_EXCEPTION. 如果不论什么原因你想抛出PHP警告,就使用PDO::ERRORMODE_WARNING.
11.3. PDO::ATTR_TIMEOUT
当你为载入时间而着急时,你可以使用些属性来为你的查询 指定一个超时时间,单位是秒,注意,如果 超过你设置的时间,缺省会抛出E_WARNING异常,除非PDO::ATTR_ERRMODE被改变.
转载