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 相关文章推荐
BBS(php &amp; mysql)完整版(七)
Oct 09 PHP
探讨php中header的用法详解
Jun 07 PHP
php遍历目录输出目录及其下的所有文件示例
Jan 27 PHP
PhpDocumentor 2安装以及生成API文档的方法
May 21 PHP
ThinkPHP之A方法实例讲解
Jun 20 PHP
是 WordPress 让 PHP 更流行了 而不是框架
Feb 03 PHP
PHP的Yii框架中行为的定义与绑定方法讲解
Mar 18 PHP
PHP数组编码gbk与utf8互相转换的两种方法
Sep 01 PHP
解决PHP使用CURL发送GET请求时传递参数的问题
Oct 11 PHP
laravel 修改记住我功能的cookie保存时间的方法
Oct 14 PHP
PHP中通过getopt解析GNU C风格命令行选项
Nov 18 PHP
PHP大文件分割分片上传实现代码
Dec 09 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
PHP4实际应用经验篇(1)
2006/10/09 PHP
typecho插件编写教程(二):写一个新插件
2015/05/28 PHP
Yii2中Restful API原理实例分析
2016/07/25 PHP
PHP实现会员账号单唯一登录的方法分析
2019/03/07 PHP
js中巧用cssText属性批量操作样式
2011/03/13 Javascript
javascript开发随笔二 动态加载js和文件
2011/11/25 Javascript
更换select下拉菜单背景样式的实现代码
2011/12/20 Javascript
借助script进行Http跨域请求:JSONP实现原理及代码
2013/03/19 Javascript
无限树Jquery插件zTree的常用功能特性总结
2014/09/11 Javascript
JavaScript中的函数嵌套使用
2015/06/04 Javascript
JavaScript的代码编写格式规范指南
2015/12/07 Javascript
jQuery电话号码验证实例
2017/01/05 Javascript
vue.js实现数据动态响应 Vue.set的简单应用
2017/06/15 Javascript
详解使用路由延迟加载 Angular 模块
2017/10/12 Javascript
VUE实现可随意拖动的弹窗组件
2018/09/25 Javascript
理理Vue细节(推荐)
2019/04/16 Javascript
通过高德地图API获得某条道路上的所有坐标用于描绘道路的方法
2020/08/24 Javascript
JavaScript 防盗链的原理以及破解方法
2020/12/29 Javascript
[04:14]从西雅图到上海——玩家自制DOTA2主题歌曲应援TI9
2019/07/11 DOTA
Python创建普通菜单示例【基于win32ui模块】
2018/05/09 Python
Pycharm+Scrapy安装并且初始化项目的方法
2019/01/15 Python
python3 tkinter实现添加图片和文本
2019/11/26 Python
销售行业个人求职自荐信
2013/09/25 职场文书
校领导推荐信
2013/11/01 职场文书
实习鉴定评语
2014/01/19 职场文书
年终总结会主持词
2014/03/25 职场文书
教师职业道德事迹材料
2014/08/18 职场文书
重点工程汇报材料
2014/08/27 职场文书
2014最新预备党员思想汇报范文:中国梦,我的梦
2014/10/25 职场文书
个人创业事迹材料
2014/12/30 职场文书
应急管理工作总结2015
2015/05/04 职场文书
2019年暑期安全广播稿!
2019/07/03 职场文书
祝福语集锦:朋友新店开业祝福语
2019/12/10 职场文书
《暗黑破坏神2:重制版》本周进行第一轮A测 目前可官网进行申请报名
2021/04/07 其他游戏
JavaWeb实现显示mysql数据库数据
2022/03/19 Java/Android
Django中celery的使用项目实例
2022/07/07 Python