PDO-PHP数据对象(PHP-Data-Object)基础详解

322 阅读6分钟

PDO-PHP数据对象

PDO(php data objct)扩展库为php访问数据库定义了轻量级的、一致性的接口,它提供了一个数据库访问抽象层,大大简化了数据库的操作,支持多种数据库。

1.PDO安装

  • PDO扩展安装非常简单,只需要在php.ini文件中将对应的扩展前面的分号去掉,然后apache即可。
extension=pdo_mysql  //mysql扩展
;extension=pdo_oci   //oracle扩展
;extension=pdo_odbc
;extension=pdo_pgsql
;extension=pdo_sqlite
;extension=pgsql
  • 编写一个.php文件使用phpinfo()函数即可查看是否开启了对应扩展。

2.创建PDO对象与连接设置

  • 创建PDO对象
$dsn = 'mysql:host=localhost;dbname=testdb'; //连接mysql数据的dsn
$dsn = "oci:dbname=//localhost/oracle;port=1521;charset=utf8";  //oracle连接方式,`localhost后面的oracle有时候是默认orcl,这里是因为安装的时候修改了`
$username = 'dbuser'; //mysql数据库的用户名
$password = 'dbpass'; //mysql数据库的密码

try {
	$dbh = new PDO($dsn,$username,$password); //new PDO对象
} catch (PDOException $e) {
	echo "数据库连接失败:".$e->getMessage();
}
  • 设置连接字符集

一般在项目中不推荐使用,为减少数据库执行次数,只要保证字符集编码保持一致,

$pdo->exec("set names utf8");
或者
$pdo->query("set names utf8");
  • 连接设置处理

设置异常处理模式(PDO::ATTR_ERRMODE)取值有如下三个:

  1. PDO::ERRMODE_SILENT 表示成功的时候不报错
  2. PDO::ERRMODE_WARNING 表示如果出错抛出一个警告
  3. PDO::ERRMODE_EXCEPTION 表示一旦出错,就会抛出一个异常(推荐使用)

设置自动提交属性(PDO::ATTR_AUTOCOMMIT)一般在使用 事务的时候用到,在进行事务处理时关闭自动提交,事务处理完成后,开启自动提交,取值如下:

  1. 0 表示关闭自动提交
  2. 1 表示开启自动提交

设置结果集返回的格式(PDO::ATTR_DEFAULT_FETCH_MODE),一般在进行数据库操作时候,要对数据返回的结果集进行规定格式,不过一般也不用设置,在需要什么格的时候再进行处理,取值如下:

  1. PDO::FETCH_ASSOC 表示返回关联数组格式(推荐)
  2. PDO::FETCH_NUM 表示返回索引数组格式(推荐)
  3. PDO::FETCH_BOTH 表示返回以上两种格式
  4. PDO::FETCH_OBJ 表示返回对象格式数据

以上代码实现如下:

<?php
try {
  $dsn = 'mysql:host=localhost;dbname=db_demo';  //设置mysql数据库驱动
  $username = 'root';  //设置数据库用户名
  $password = 'root';  //设置用户密码

  $pdo = new PDO($dsn, $username, $password); //实例化pdo对象
  // var_dump($pdo);   //输出有pdo对象则说明连接数据库成功
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  //设置异常处理模式为一旦出错则会抛出一个异常,也可以直接使用以下数值设置,但是不推荐
  // $pdo->setAttribute(3,2);

  // $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0); //设置关闭自动提交,默认是开启的,一般在进行事务处理的时候设置

  $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);   //设置返回的结果集格式为关联数组,一般推荐设置为关联数组或者索引数组即可
} catch (PDOException $e) {
  echo $e->getMessage();  //获取异常信息
  echo $e->getFile();     //获取异常文件
  echo $e->getLine();     //获取异常文件行
  echo $e->getCode();     //获取异常code
}

3.使用PDO对象

  • 执行数据库操作

在PDO中对数据库语句进行操作可以使用以下两种方式:

  1. PDO::exec 一般用于执行对数据库行、结构有影响的操作,比如增删改等
  2. PDO::query 一般用于不会影响行数据的操作,比如查询信息等
<?php
try {
  $dsn = 'mysql:host=localhost;dbname=phptest';
  $username = 'root';
  $password = 'root';

  $pdo = new PDO($dsn, $username, $password);
  $username = 'qunqun';
  $age = 20;
  // 执行语句并接收结果,结果为所影响的行数
  // $affectRow = $pdo->exec("insert into user(username,age) values('$username','$age')");
  // echo $affectRow;

  // 使用query执行语句,对有结果集进行查询
  // 返回的是一个PDOStatement对象结果集,已经直接对这个对象进行遍历
  $stmt = $pdo->query("select * from user");
  foreach ($stmt as $v) {
    echo "{$v['id']}-{$v['username']}-{$v['age']}<br />";
  }
  var_dump($stmt);
} catch (PDOException $e) {
  echo $e->getMessage();
}

4.PDO预处理

项目中推荐使用PDO的预处理对象,因为它更加安全,更加高效,因为在使用的过程中,SQL语句只会被编译一次,能有效防止SQL注入。

  • PDOStatement对象的方法
  • 准备语句
  • 绑定参数
  • 执行预处理方式
  • 预处理查询

方式一:使用占位符方式绑定参数

<?php
include("pdo.php");
try {
  // 方式1:语句直接使用?作为占位符使用
  // 1.sql语句
  $sql = "insert into user(username,age) values(?,?)";
  // 2.使用prepare()方法预编译语句
  $stmt = $pdo->prepare($sql);
  // 3.为上面使用占位符的地方绑定参数
  $stmt->bindParam(1, $username);  //注意:此处绑定参数只能使用参数,不能直接写值,不然会报错
  $stmt->bindParam(2, $age);

  // 4.为参数设置具体的值
  $username = "admin";
  $age = 18;

  // 5.做完以上步骤,执行语句,会返回一个bool值
  $stmt->execute();

  // 当然:以上3-5步可以合成一步执行,传入的参数需要使用索引数据格式
  // $stmt->execute(array("admin1", 100));
} catch (PDOException $e) {
  echo $e->getMessage();
}

方式二:使用别名方式绑定参数

<?php
include("pdo.php");
try {
  // 1.准备sql语句,使用别名方式绑定
  $sql = "insert into user(username,age) values(:username,:age)";
  // 2.预编译语句
  $stmt = $pdo->prepare($sql);
  // 3.绑定相应参数
  // $stmt->bindParam(":username", $username);
  // $stmt->bindParam(":age", $age);
  // // 4.设置参数值
  // $username = "admin2";
  // $age = 2;
  // // 5.执行语句
  // $stmt->execute();

  // 同样,以上3-5步也有简写方式,但是传的参数必须是关联数组,key要与别名一一对应
  $arr = array("username" => "admin3", "age" => '2');
  $stmt->execute($arr);
} catch (PDOException $e) {
  echo $e->getMessage();
}

预处理查询

  • 使用fetch()方法接收到一条结果集对象
<?php
include("pdo.php");
try {
  // 执行返回结果集的操作
  // 1.sql语句
  $sql = "select * from user where id=:id";  //id使用别名方式获取
  // 2.预编译sql
  $stmt = $pdo->prepare($sql);
  // 3.执行语句,使用$_GET获取参数并传参
  $stmt->execute($_GET);
  // 4.从结果集中获取一条数据
  // fecth()函数中可以设置返回的数据格式,一般为关联数组
  $user = $stmt->fetch(PDO::FETCH_ASSOC);
  var_dump($user);
} catch (PDOException $e) {
  echo $e->getMessage();
}
  • 使用fetchAll()方法接收多条结果集
<?php
include("pdo.php");
try {
  // 执行返回结果集的操作
  // 1.sql语句
  $sql = "select * from user where id > :id";  //id使用别名方式获取
  // 2.预编译sql
  $stmt = $pdo->prepare($sql);
  // 3.执行语句,使用$_GET获取参数并传参
  $stmt->execute($_GET);
  // 4.从结果集中获取一条数据
  // fecth()函数中可以设置返回的数据格式,一般为关联数组
  // $user = $stmt->fetch(PDO::FETCH_ASSOC);
  $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
  var_dump($users);
} catch (PDOException $e) {
  echo $e->getMessage();
}
  • rowCount()方法
// rowCount 方法返回上一个sql语句所影响的行数
$affectRows = $stmt->rowCount();

5.PDO事务处理

事务表示的是一整个流程,一个事务中可能包含多个操作,要所有的操作都成功才会算成功,否则算失败,拿个例子说:两个人,一人银行汇钱给另外一个,汇钱方成功转款,但是接收方并没有接收到,这时候就是失败的,要进行回滚操作,只要两方需要的操作成功才算成功。

  • 在原生mysql命令行中开启事务
start transaction;
  • 如果需要进行回滚操作,执行以下命令即可
(回滚操作成功需要在开启事务的时候才会触发)
roolback;
  • 结束事务
事务结束后再回滚不生效
commit;

使用PDO进行事务处理

比如就拿汇款这个例子进行编码

<?php
include("pdo.php");

try {
  // 1.开启事务之前要将自动提交关闭
  $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);
  // 2.开启事务
  $pdo->beginTransaction();

  // 3.执行转出操作
  $sql = "UPDATE crsh SET money = money -50 where username='zhangsan'";
  // 由于sql没有参数,就不用预处理prepare()了,直接使用exec()方法
  $affectRow =  $pdo->exec($sql); // 返回一个影响行
  if (!$affectRow) {
    throw new PDOException("转出失败!");
  }
  // 上面的执行成功才会执行下面
  $sql = "UPDATE crsh SET money = money +50 where username='lisi'";
  $affectRow =  $pdo->exec($sql); // 返回一个影响行
  if (!$affectRow) {
    throw new PDOException("转入失败!");
  }
  // 都成功执行后关闭事务
  $pdo->commit();
  echo "汇款成功!";
} catch (PDOException $e) {
  echo $e->getMessage();
  // 事务失败时进行回滚操作
  $pdo->rollBack();
}

// 不管成功与否,都需要在结束时将自动提交打开
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);

PDO-PHP数据对象

PDO(php data objct)扩展库为php访问数据库定义了轻量级的、一致性的接口,它提供了一个数据库访问抽象层,大大简化了数据库的操作,支持多种数据库。

1.PDO安装

  • PDO扩展安装非常简单,只需要在php.ini文件中将对应的扩展前面的分号去掉,然后apache即可。
extension=pdo_mysql  //mysql扩展
;extension=pdo_oci   //oracle扩展
;extension=pdo_odbc
;extension=pdo_pgsql
;extension=pdo_sqlite
;extension=pgsql
  • 编写一个.php文件使用phpinfo()函数即可查看是否开启了对应扩展。

2.创建PDO对象与连接设置

  • 创建PDO对象
$dsn = 'mysql:host=localhost;dbname=testdb'; //连接mysql数据的dsn
$username = 'dbuser'; //mysql数据库的用户名
$password = 'dbpass'; //mysql数据库的密码

try {
	$dbh = new PDO($dsn,$username,$password); //new PDO对象
} catch (PDOException $e) {
	echo "数据库连接失败:".$e->getMessage();
}
  • 设置连接字符集

一般在项目中不推荐使用,为减少数据库执行次数,只要保证字符集编码保持一致,

$pdo->exec("set names utf8");
或者
$pdo->query("set names utf8");
  • 连接设置处理

设置异常处理模式(PDO::ATTR_ERRMODE)取值有如下三个:

  1. PDO::ERRMODE_SILENT 表示成功的时候不报错
  2. PDO::ERRMODE_WARNING 表示如果出错抛出一个警告
  3. PDO::ERRMODE_EXCEPTION 表示一旦出错,就会抛出一个异常(推荐使用)

设置自动提交属性(PDO::ATTR_AUTOCOMMIT)一般在使用 事务的时候用到,在进行事务处理时关闭自动提交,事务处理完成后,开启自动提交,取值如下:

  1. 0 表示关闭自动提交
  2. 1 表示开启自动提交

设置结果集返回的格式(PDO::ATTR_DEFAULT_FETCH_MODE),一般在进行数据库操作时候,要对数据返回的结果集进行规定格式,不过一般也不用设置,在需要什么格的时候再进行处理,取值如下:

  1. PDO::FETCH_ASSOC 表示返回关联数组格式(推荐)
  2. PDO::FETCH_NUM 表示返回索引数组格式(推荐)
  3. PDO::FETCH_BOTH 表示返回以上两种格式
  4. PDO::FETCH_OBJ 表示返回对象格式数据

以上代码实现如下:

<?php
try {
  $dsn = 'mysql:host=localhost;dbname=db_demo';  //设置mysql数据库驱动
  $username = 'root';  //设置数据库用户名
  $password = 'root';  //设置用户密码

  $pdo = new PDO($dsn, $username, $password); //实例化pdo对象
  // var_dump($pdo);   //输出有pdo对象则说明连接数据库成功
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  //设置异常处理模式为一旦出错则会抛出一个异常,也可以直接使用以下数值设置,但是不推荐
  // $pdo->setAttribute(3,2);

  // $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0); //设置关闭自动提交,默认是开启的,一般在进行事务处理的时候设置

  $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);   //设置返回的结果集格式为关联数组,一般推荐设置为关联数组或者索引数组即可
} catch (PDOException $e) {
  echo $e->getMessage();  //获取异常信息
  echo $e->getFile();     //获取异常文件
  echo $e->getLine();     //获取异常文件行
  echo $e->getCode();     //获取异常code
}

3.使用PDO对象

  • 执行数据库操作

在PDO中对数据库语句进行操作可以使用以下两种方式:

  1. PDO::exec 一般用于执行对数据库行、结构有影响的操作,比如增删改等
  2. PDO::query 一般用于不会影响行数据的操作,比如查询信息等
<?php
try {
  $dsn = 'mysql:host=localhost;dbname=phptest';
  $username = 'root';
  $password = 'root';

  $pdo = new PDO($dsn, $username, $password);
  $username = 'qunqun';
  $age = 20;
  // 执行语句并接收结果,结果为所影响的行数
  // $affectRow = $pdo->exec("insert into user(username,age) values('$username','$age')");
  // echo $affectRow;

  // 使用query执行语句,对有结果集进行查询
  // 返回的是一个PDOStatement对象结果集,已经直接对这个对象进行遍历
  $stmt = $pdo->query("select * from user");
  foreach ($stmt as $v) {
    echo "{$v['id']}-{$v['username']}-{$v['age']}<br />";
  }
  var_dump($stmt);
} catch (PDOException $e) {
  echo $e->getMessage();
}

4.PDO预处理

项目中推荐使用PDO的预处理对象,因为它更加安全,更加高效,因为在使用的过程中,SQL语句只会被编译一次,能有效防止SQL注入。

  • PDOStatement对象的方法
  • 准备语句
  • 绑定参数
  • 执行预处理方式
  • 预处理查询

方式一:使用占位符方式绑定参数

<?php
include("pdo.php");
try {
  // 方式1:语句直接使用?作为占位符使用
  // 1.sql语句
  $sql = "insert into user(username,age) values(?,?)";
  // 2.使用prepare()方法预编译语句
  $stmt = $pdo->prepare($sql);
  // 3.为上面使用占位符的地方绑定参数
  $stmt->bindParam(1, $username);  //注意:此处绑定参数只能使用参数,不能直接写值,不然会报错
  $stmt->bindParam(2, $age);

  // 4.为参数设置具体的值
  $username = "admin";
  $age = 18;

  // 5.做完以上步骤,执行语句,会返回一个bool值
  $stmt->execute();

  // 当然:以上3-5步可以合成一步执行,传入的参数需要使用索引数据格式
  // $stmt->execute(array("admin1", 100));
} catch (PDOException $e) {
  echo $e->getMessage();
}

方式二:使用别名方式绑定参数

<?php
include("pdo.php");
try {
  // 1.准备sql语句,使用别名方式绑定
  $sql = "insert into user(username,age) values(:username,:age)";
  // 2.预编译语句
  $stmt = $pdo->prepare($sql);
  // 3.绑定相应参数
  // $stmt->bindParam(":username", $username);
  // $stmt->bindParam(":age", $age);
  // // 4.设置参数值
  // $username = "admin2";
  // $age = 2;
  // // 5.执行语句
  // $stmt->execute();

  // 同样,以上3-5步也有简写方式,但是传的参数必须是关联数组,key要与别名一一对应
  $arr = array("username" => "admin3", "age" => '2');
  $stmt->execute($arr);
} catch (PDOException $e) {
  echo $e->getMessage();
}

预处理查询

  • 使用fetch()方法接收到一条结果集对象
<?php
include("pdo.php");
try {
  // 执行返回结果集的操作
  // 1.sql语句
  $sql = "select * from user where id=:id";  //id使用别名方式获取
  // 2.预编译sql
  $stmt = $pdo->prepare($sql);
  // 3.执行语句,使用$_GET获取参数并传参
  $stmt->execute($_GET);
  // 4.从结果集中获取一条数据
  // fecth()函数中可以设置返回的数据格式,一般为关联数组
  $user = $stmt->fetch(PDO::FETCH_ASSOC);
  var_dump($user);
} catch (PDOException $e) {
  echo $e->getMessage();
}
  • 使用fetchAll()方法接收多条结果集
<?php
include("pdo.php");
try {
  // 执行返回结果集的操作
  // 1.sql语句
  $sql = "select * from user where id > :id";  //id使用别名方式获取
  // 2.预编译sql
  $stmt = $pdo->prepare($sql);
  // 3.执行语句,使用$_GET获取参数并传参
  $stmt->execute($_GET);
  // 4.从结果集中获取一条数据
  // fecth()函数中可以设置返回的数据格式,一般为关联数组
  // $user = $stmt->fetch(PDO::FETCH_ASSOC);
  $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
  var_dump($users);
} catch (PDOException $e) {
  echo $e->getMessage();
}
  • rowCount()方法
// rowCount 方法返回上一个sql语句所影响的行数
$affectRows = $stmt->rowCount();

5.PDO事务处理

事务表示的是一整个流程,一个事务中可能包含多个操作,要所有的操作都成功才会算成功,否则算失败,拿个例子说:两个人,一人银行汇钱给另外一个,汇钱方成功转款,但是接收方并没有接收到,这时候就是失败的,要进行回滚操作,只要两方需要的操作成功才算成功。

  • 在原生mysql命令行中开启事务
start transaction;
  • 如果需要进行回滚操作,执行以下命令即可
(回滚操作成功需要在开启事务的时候才会触发)
roolback;
  • 结束事务
事务结束后再回滚不生效
commit;

使用PDO进行事务处理

比如就拿汇款这个例子进行编码

<?php
include("pdo.php");

try {
  // 1.开启事务之前要将自动提交关闭
  $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);
  // 2.开启事务
  $pdo->beginTransaction();

  // 3.执行转出操作
  $sql = "UPDATE crsh SET money = money -50 where username='zhangsan'";
  // 由于sql没有参数,就不用预处理prepare()了,直接使用exec()方法
  $affectRow =  $pdo->exec($sql); // 返回一个影响行
  if (!$affectRow) {
    throw new PDOException("转出失败!");
  }
  // 上面的执行成功才会执行下面
  $sql = "UPDATE crsh SET money = money +50 where username='lisi'";
  $affectRow =  $pdo->exec($sql); // 返回一个影响行
  if (!$affectRow) {
    throw new PDOException("转入失败!");
  }
  // 都成功执行后关闭事务
  $pdo->commit();
  echo "汇款成功!";
} catch (PDOException $e) {
  echo $e->getMessage();
  // 事务失败时进行回滚操作
  $pdo->rollBack();
}

// 不管成功与否,都需要在结束时将自动提交打开
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);

以上就是PDO用于操作数据库的基础,便于自查