Laravel如何使用数据库事务及捕获事务失败后的异常详解


Posted in PHP onOctober 23, 2017

前言

如果大家在Laravel中要想在数据库事务中运行一组操作,则可以在 DB facade 中使用 transaction 方法。如果在事务的闭包内抛出异常,事务将会被自动还原。如果闭包运行成功,事务将被自动提交。

你不需要担心在使用 transaction 方法时还需要亲自去手动还原或提交事务:

DB::transaction(function () {
 DB::table('users')->update(['votes' => 1]);

 DB::table('posts')->delete();
});

手动操作事务

如果你想手动处理事务并对还原或提交操作进行完全控制,则可以在 DB facade 使用 beginTransaction 方法:

DB::beginTransaction();

你也可以通过 rollBack 方法来还原事务:

DB::rollBack();

最后,可以通过 commit 方法来提交这个事务:

DB::commit();

注意: DB facade 的事务方法也可以用来控制 查询语句构造器 及 Eloquent ORM 的事务。

示例介绍

假设有要在数据库中存储一个知识点,这个知识点同时属于两个不同的考点,也就是考点和知识点这两个数据是多对多的关系,那么要实现这种数据结构就需要三个表:

知识点表 wiki:

---------------------------------------
id  title    content
---------------------------------------

考点表 tag:

-------------------
id  name
-------------------

考点知识点关联表 wiki_tag_rel

----------------------------------
id   tag_id  wiki_id
----------------------------------

现在要开启事务新增Wiki数据,新增wiki成功后再把它关联到指定的考点上去

(在laravel中使用查询构建器或者Eloquent ORM执行query时,如果失败会返回 Illuminate\Database\QueryException 异常)

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Database\QueryException;
use App\Wiki;

class TestController extends Controller
{
 //用DB facade的事务方法控制 查询语句构建器的事务
 public function storeWiki(Request $request)
 {
  DB::beginTransaction();
  try {
   $tagIds = explode(',', $request->get('tag_id'));
   $wiki_id = DB::table('wiki')->insertGetId([
    'title' => $request->get('title'),
    'content' => $request->get('content')
   ]);

   $relationData = [];
   foreach($tagIds as $tagId) {
    $data = ['wiki_id' => $wiki_id, 'tag_id' => $tagId];
    $relationData[] = $data;
   }
   DB::table('wiki_tag_rel')->insert($relationData);
   DB::commit();
  } catch(\Illuminate\Database\QueryException $ex) {
   DB::rollback();
   return \Response::json(['status' => 'error', 'error_msg' => 'Failed, please contact supervisor']);
  }
  
  return \Response::json(['status' => 'ok']);
 }


 //用DB facade的事务方法控制 Eloquent ORM的事务
 public function createWiki(array $data)
 {
  DB::beginTransaction();
  try {
   $tagIds = explode(',', $data['tag_id']);
   $newWiki = Wiki::create([
    'title' => $data['title'],
    'content' => $data['content']
   ]);
   //Wiki和Tag两个Model使用了belongsToMany建立了多对多的关系
   //通过attach方法来附加wiki和tag的关系(写入中间表)
   $newWiki->tags()->attach($tagIds);
   DB::commit();
  } catch(QueryException $ex) {
   DB::rollback();
   return \Response::json(['status' => 'error', 'error_msg' => 'Failed, please contact supervisor']);
  }

  return \Response::json(['status' => 'ok']);
  }

}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
收集的PHP中与数组相关的函数
Mar 22 PHP
PHP获取数组中某元素的位置及array_keys函数应用
Jan 29 PHP
Windows下的PHP 5.3.x安装 Zend Guard Loader教程
Sep 06 PHP
php编写的一个E-mail验证类
Mar 25 PHP
php自动更新版权信息显示的方法
Jun 19 PHP
PHP生成唯一订单号
Jul 05 PHP
浅析Yii2缓存的使用
May 10 PHP
PHP下载文件的函数实例代码
May 18 PHP
PHP入门教程之面向对象的特性分析(继承,多态,接口,抽象类,抽象方法等)
Sep 11 PHP
php中输出json对象的值(实现方法)
Mar 07 PHP
详解关于php的xdebug配置(编辑器vscode)
Jan 29 PHP
PHP数组基本用法与知识点总结
Jun 02 PHP
PHP实现实时生成并下载超大数据量的EXCEL文件详解
Oct 23 #PHP
Laravel学习教程之model validation的使用示例
Oct 23 #PHP
laravel实现批量更新多条记录的方法示例
Oct 22 #PHP
利用PHP获取汉字首字母并且分组排序详解
Oct 22 #PHP
Laravel 5.4因特殊字段太长导致migrations报错的解决
Oct 22 #PHP
PHP高效获取远程图片尺寸和大小的实现方法
Oct 20 #PHP
PHP静态延迟绑定和普通静态效率的对比
Oct 20 #PHP
You might like
全国FM电台频率大全 - 1 北京市
2020/03/11 无线电
POSIX 风格和兼容 Perl 风格两种正则表达式主要函数的类比(preg_match, preg_replace, ereg, ereg_replace)
2010/10/12 PHP
ajax 的post方法实例(带循环)
2011/07/04 PHP
分享一段php获取linux服务器状态的代码
2014/05/27 PHP
php用正则判断是否为数字的方法
2016/03/25 PHP
PHP数组式访问接口ArrayAccess用法分析
2017/12/28 PHP
jscript之List Excel Color Values
2007/06/13 Javascript
js判断屏幕分辨率的代码
2013/07/16 Javascript
JS操作JSON要领详细总结
2013/08/25 Javascript
js取消单选按钮选中并判断对象是否为空
2013/11/14 Javascript
jQuery选择器全面总结
2014/01/06 Javascript
JavaScript fontsize方法入门实例(按照指定的尺寸来显示字符串)
2014/10/17 Javascript
在JavaScript中操作时间之getUTCDate()方法的使用
2015/06/10 Javascript
详解JavaScript的策略模式编程
2015/06/24 Javascript
微信小程序侧边栏滑动特效(左右滑动)
2017/01/23 Javascript
ionic 3.0+ 项目搭建运行环境的教程
2017/08/09 Javascript
基于js原生和ajax的get和post方法以及jsonp的原生写法实例
2017/10/16 Javascript
35个最好用的Vue开源库(史上最全)
2019/01/03 Javascript
vue2配置scss的方法步骤
2019/06/06 Javascript
Python获取当前路径实现代码
2017/05/08 Python
python实现登录密码重置简易操作代码
2019/08/14 Python
Python ini文件常用操作方法解析
2020/04/26 Python
PyInstaller的安装和使用的详细步骤
2020/06/02 Python
python logging 重复写日志问题解决办法详解
2020/08/04 Python
selenium切换标签页解决get超时问题的完整代码
2020/08/30 Python
python+selenium+chrome实现淘宝购物车秒杀自动结算
2021/01/07 Python
python中Array和DataFrame相互转换的实例讲解
2021/02/03 Python
基于html5 DeviceOrientation 实现微信摇一摇功能
2015/09/25 HTML / CSS
JD Sports德国官网:英国领先的运动鞋和运动服饰零售商
2018/02/26 全球购物
美国一站式电动和手动工具商店:International Tool
2020/11/26 全球购物
资源环境与城乡规划管理专业自荐书
2014/09/26 职场文书
开幕式邀请函
2015/01/31 职场文书
计划生育个人总结
2015/03/02 职场文书
2015年度优秀员工推荐信
2015/03/23 职场文书
redis数据一致性的实现示例
2022/03/18 Redis
MySQL count(*)统计总数问题汇总
2022/09/23 MySQL