PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。
PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。
PHP 5 >= 5.1.0, PECL pdo >= 0.1.0)
一、PDO连接
连接是通过创建 PDO 基类的实例而建立的。不管使用哪种驱动程序,都是用 PDO 类名。
1、连接到 MySQL
<?php
//1.实例化PDO类,创建PDO对象
$pdo = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
?>
2、处理连接错误
<?php
try{
//1.实例化PDO类,创建PDO对象
$pdo = new PDO('mysql:host=localhost;dbname=test','root','123456');
// 在此使用连接
...
// 现在运行完成,在此关闭连接
$pdo = null;
}catch(PDOException $e){
//抛出错误
die('数据库错误:'.$e->getMessage());
}
注意
连接数据成功后,返回一个 PDO 类的实例给脚本,此连接在 PDO 对象的生存周期中保持活动。
要想关闭连接,需要销毁对象以确保所有剩余到它的引用都被删除,可以赋一个 NULL 值给对象变量。
如果不这么做,PHP 在脚本结束时会自动关闭连接。
3、封装PDO函数
/**
* 数据库连接
* @param $db
* @return PDO
*/
function connect(){
$db = array(
'type' => 'mysql', //数据库类型
'host' => '127.0.0.1', //数据库主机名
'user' => 'root', //数据库连接用户名
'pass' => '123456', //对应的密码
'name' => 'test' //使用的数据库
'charset' => 'utf8', //字符集
'port' => 3306, //端口号
);
$dsn = "{$db['type']}:host={$db['host']}; dbname={$db['name']}; charset={$db['charset']}; port={$db['port']}";
try {
//1.实例化PDO类,创建PDO对象
$pdo = new PDO($dsn,$db['user'],$db['pass']);
} catch (PDOException $e) {
die('数据库错误:'.$e->getMessage());
}
return $pdo;
}
二、PHP PDO 类与PDOStatement 类
1、PDO::prepare
PDO::prepare — 准备要执行的SQL语句并返回一个 PDOStatement 对象
// 2.预处理sql语句
$pre = $pdo -> prepare('SELECT * FROM `tp_user`');
var_dump($pre);
为 PDOStatement::execute() 方法准备要执行的SQL语句,SQL语句可以包含零个或多个命名(:name)或问号(?)参数标记,参数在SQL执行时会被替换。
不能在 SQL 语句中同时包含命名(:name)或问号(?)参数标记,只能选择其中一种风格。
2、PDOStatement::execute
PDOStatement::execute — 执行一条预处理语句
// execute() 执行sql语句(读/写)
// 3.执行sql语句
$exe = $pre -> execute();
执行预处理过的语句。如果预处理过的语句含有参数标记,必须选择下面其中一种做法:
- 调用 PDOStatement::bindParam 绑定 PHP 变量到参数标记:如果有的话,通过关联参数标记绑定的变量来传递输入值和取得输出值
- 或传递一个只作为输入参数值的数组
3、PDOStatement::bindParam
PDOStatement::bindParam — 绑定一个参数到指定的变量名
$pre -> bindParam(':username',$username,PDO::PARAM_STR);
$pre -> bindParam(':age', $calories, PDO::PARAM_INT);
绑定一个PHP变量到用作预处理的SQL语句中的对应命名占位符或问号占位符。
4、PDOStatement::fetchAll
PDOStatement::fetchAll — 返回一个包含结果集中所有行的数组
// 4.返回结果集
$pre = $pdo -> prepare('SELECT * FROM `user`');
$exe = $pre -> execute();;
$data = $pre -> fetchAll();
print_r($data);
5、PDOStatement::fetch
PDOStatement::fetch — 从结果集中获取下一行
//5.fetch() 查询出来是一维数据
$pre = $pdo -> prepare('SELECT * FROM `user` WHERE `id`=25');
$exe = $pre -> execute();
$data = $pre -> fetch();
print_r($data);
三、PHP PDO 预处理语句
什么是预处理语句?可以把它看作是想要运行的 SQL 的一种编译过的模板,它可以使用变量参数进行定制。预处理语句可以带来两大好处:
- 查询仅需解析(或预处理)一次,但可以用相同或不同的参数执行多次。当查询准备好后,数据库将分析、编译和优化执行该查询的计划。对于复杂的查询,此过程要花费较长的时间,如果需要以不同参数多次重复相同的查询,那么该过程将大大降低应用程序的速度。通过使用预处理语句,可以避免重复分析/编译/优化周期。简言之,预处理语句占用更少的资源,因而运行得更快。
- 提供给预处理语句的参数不需要用引号括起来,驱动程序会自动处理。如果应用程序只使用预处理语句,可以确保不会发生SQL 注入。(然而,如果查询的其他部分是由未转义的输入来构建的,则仍存在 SQL 注入的风险)。
1、执行一条使用命名占位符的预处理语句
<?php
/* 通过绑定的 PHP 变量执行一条预处理语句 */
$sql = 'INSERT INTO `user` SET `username`=:username,`phone`=:phone,`sex`=:sex,`age`=:age,`addtime`=:addtime';
$pre = $pdo -> prepare($sql);
// bindParam 参数绑定
// // 1. 站位符名
// // 2. 要给值得变量,绑定上,现在可以没值
// // 3. 常量,pdo预定义常量,可以设置这个值的类型 ,访问方式: PDO:: ,类里的常量访问方式
$pre -> bindParam('username',$username,PDO::PARAM_STR);
$pre -> bindParam('phone',$phone,PDO::PARAM_STR);
$pre -> bindParam('sex',$sex,PDO::PARAM_STR);
$pre -> bindParam('age',$age,PDO::PARAM_STR);
$pre -> bindParam('addtime',$addtime,PDO::PARAM_STR);
$username = '小北';
$phone = '1534874623';
$sex = 0;
$age = '18';
$addtime = time();
$exe = $pre -> execute();h->bindParam('age', $age, PDO::PARAM_INT);
$sth->execute();
if(!$exe){
//将错误信息打印出来
print_r($pre->errorInfo());
}else{
// rowCount 获取是否成功,影响数量
echo $pre -> rowCount();
echo '<hr>';
// lastinsertId 获取这次自增的id,类是用的链接的类pod
echo $pdo -> lastInsertId();
}
?>
2、执行一条使用问号占位符的预处理语句
<?php
$sql = 'INSERT INTO `user` SET `username`=?,`phone`=?,`sex`=?,`age`=?';
$pre = $pdo -> prepare($sql);
$pre -> bindParam(1,$username,PDO::PARAM_STR);
$pre -> bindParam(3,$phone,PDO::PARAM_STR);
$pre -> bindParam(4,$sex,PDO::PARAM_STR);
$pre -> bindParam(5,$age,PDO::PARAM_STR);
$username = '小北';
$phone = '1534874623';
$sex = 0;
$age = '18';
$exe = $pre -> execute();
if(!$exe){
//将错误信息打印出来
print_r($pre->errorInfo());
}else{
// rowCount 获取是否成功,影响数量
echo $pre -> rowCount();
echo '<hr>';
// lastinsertId 获取这次自增的id,类是用的链接的类pod
echo $pdo -> lastInsertId();
}
?>
3、明文占位,数组传值,并且不需要绑定数据,直接在execute 传数组
$sql = 'INSERT INTO `user` SET `username`=:username,`phone`=:phone,`sex`=:sex,`age`=:age,`addtime`=:addtime';
$pre = $pdo -> prepare($sql);
$exe = $pre -> execute([
':username' => 'zhangsan',
':phone' => 13146529855,
':sex' => 1,
':age' => 25,
':addtime' => $time
]);
if(!$exe){
print_r($pre->errorInfo());
}else{
echo $pre -> rowCount();
echo '<hr>';
echo $pdo -> lastInsertId();
}
4、? 号占位,数组传值,并且不需要绑定数据,直接在execute 传数组
$sql = 'INSERT INTO `user` SET `username`=?,`phone`=?,`sex`=?,`age`=?,`addtime`=?';
$pre = $pdo -> prepare($sql);
$exe = $pre -> execute([
'小北2',
13416265984,
1,
20,
$time
]);
if(!$exe){
print_r($pre->errorInfo());
}else{
echo $pre -> rowCount();
echo '<hr>';
echo $pdo -> lastInsertId();
}