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 相关文章推荐
Uchome1.2 1.5 代码学习 common.php
Apr 24 PHP
php $_SERVER[&quot;REQUEST_URI&quot;]获取值的通用解决方法
Jun 21 PHP
php中禁止单个IP与ip段访问的代码小结
Jul 04 PHP
php中定时计划任务的实现原理
Jan 08 PHP
php使用codebase生成随机数
Mar 25 PHP
利用php下载xls文件(自己动手写的)
Apr 18 PHP
PHP学习笔记(一) 简单了解PHP
Aug 04 PHP
PHP多线程之内部多线程实例分析
Mar 09 PHP
全面解读PHP的Yii框架中的日志功能
Mar 17 PHP
php实现图片缩略图的方法
Mar 29 PHP
PHP简单获取及判断提交来源的方法
Apr 22 PHP
PHP实现表单提交时去除斜杠的方法
Dec 26 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
mysql From_unixtime及UNIX_TIMESTAMP及DATE_FORMAT日期函数
2010/03/21 PHP
smarty巧妙处理iframe中内容页的代码
2012/03/07 PHP
PHP实现获取中英文首字母
2015/06/19 PHP
PHP中file_put_contents追加和换行的实现方法
2017/04/01 PHP
犀利的js 函数集合
2009/06/11 Javascript
js对table的td进行相同内容合并示例详解
2013/12/27 Javascript
JavaScript在Android的WebView中parseInt函数转换不正确问题解决方法
2015/04/25 Javascript
BootStrap智能表单实战系列(四)表单布局介绍
2016/06/13 Javascript
详解JavaScript树结构
2017/01/09 Javascript
jQuery快速实现商品数量加减的方法
2017/02/06 Javascript
Bootstrap table学习笔记(2) 前后端分页模糊查询
2017/05/18 Javascript
jQuery实现定时隐藏对话框的方法分析
2018/02/12 jQuery
轻松搞定jQuery+JSONP跨域请求的解决方案
2018/03/06 jQuery
Vue动态获取width的方法
2018/08/22 Javascript
微信小程序websocket聊天室的实现示例代码
2019/02/12 Javascript
在Web关闭页面时发送Ajax请求的实现方法
2019/03/07 Javascript
从零到一详聊创建Vue工程及遇到的常见问题
2019/04/25 Javascript
VUE.js实现动态设置输入框disabled属性
2019/10/28 Javascript
python静态方法实例
2015/01/14 Python
python+pandas+时间、日期以及时间序列处理方法
2018/07/10 Python
通过pykafka接收Kafka消息队列的方法
2018/12/27 Python
Python中psutil的介绍与用法
2019/05/02 Python
python3发送邮件需要经过代理服务器的示例代码
2019/07/25 Python
Django在admin后台集成TinyMCE富文本编辑器的例子
2019/08/09 Python
pytorch 在sequential中使用view来reshape的例子
2019/08/20 Python
matplotlib实现显示伪彩色图像及色度条
2019/12/07 Python
pytorch 批次遍历数据集打印数据的例子
2019/12/30 Python
python图形开发GUI库pyqt5的详细使用方法及各控件的属性与方法
2020/02/14 Python
Selenium结合BeautifulSoup4编写简单的python爬虫
2020/11/06 Python
Python3利用openpyxl读写Excel文件的方法实例
2021/02/03 Python
AmazeUI 单选框和多选框的实现示例
2020/08/18 HTML / CSS
瑞士国际航空官网:SWISS
2016/07/21 全球购物
环保建议书300字
2014/05/14 职场文书
党章培训心得体会
2014/09/04 职场文书
借钱欠条怎么写
2015/07/03 职场文书
励志正能量20句:送给所有为梦想拼搏的人
2019/11/11 职场文书