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工厂模式的好处
Jun 18 PHP
奉献出一个封装的curl函数 便于调用(抓数据专用)
Jul 22 PHP
thinkphp判断访客为手机端或PC端的方法
Nov 24 PHP
使用Thinkphp框架开发移动端接口
Aug 05 PHP
深入浅析php中sprintf与printf函数的用法及区别
Jan 08 PHP
PHP中explode函数和split函数的区别小结
Aug 24 PHP
PHP GD库相关图像生成和处理函数小结
Sep 30 PHP
PHP中多线程的两个实现方法
Oct 14 PHP
在laravel中使用Symfony的Crawler组件分析HTML
Jun 19 PHP
centos7上编译安装php7以php-fpm方式连接apache
Nov 08 PHP
php和vue配合使用技巧和方法
May 09 PHP
Laravel框架控制器的middleware中间件用法分析
Sep 30 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
用PHP的ob_start() 控制您的浏览器cache
2009/08/03 PHP
php生成略缩图代码
2012/07/16 PHP
PHP操作Memcache实例介绍
2013/06/14 PHP
php session实现多级目录存放实现代码
2016/02/03 PHP
iOS自定义提示弹出框实现类似UIAlertView的效果
2016/11/16 PHP
PHP levenshtein()函数用法讲解
2019/03/08 PHP
jquery插件制作简单示例说明
2012/02/03 Javascript
使用jQuery仿苹果官网焦点图特效
2014/12/23 Javascript
js实现延迟加载的方法
2015/06/24 Javascript
jQuery基于BootStrap样式实现无限极地区联动
2016/08/26 Javascript
Angularjs中的ui-bootstrap的使用教程
2017/02/19 Javascript
微信小程序实现带刻度尺滑块功能
2017/03/29 Javascript
浅谈jQuery框架Ajax常用选项
2017/07/08 jQuery
快速掌握jquery分页插件jqPaginator的使用方法
2017/08/09 jQuery
Vue 表单控件绑定的实现示例
2017/08/11 Javascript
微信小程序实现倒计时60s获取验证码
2020/04/17 Javascript
一个超级简单的python web程序
2014/09/11 Python
python中列表元素连接方法join用法实例
2015/04/07 Python
Python 关于反射和类的特殊成员方法
2017/09/14 Python
关于Tensorflow中的tf.train.batch函数的使用
2018/04/24 Python
python 梯度法求解函数极值的实例
2019/07/10 Python
HTML5的自定义属性data-*详细介绍和JS操作实例
2014/04/10 HTML / CSS
实例教程 利用html5和css3打造一款创意404页面
2014/10/20 HTML / CSS
Giuseppe Zanotti美国官方网站:将鞋履视为高级时装般精心制作
2018/02/06 全球购物
人事专员岗位职责
2013/11/20 职场文书
网络管理专业求职信
2014/03/15 职场文书
《庐山的云雾》教学反思
2014/04/22 职场文书
国际贸易实训报告
2014/11/05 职场文书
护士个人年度总结范文
2015/02/13 职场文书
2015年七一建党节慰问信
2015/03/23 职场文书
正规借条模板
2015/05/26 职场文书
2016年度继续教育学习心得体会
2016/01/19 职场文书
《海上日出》教学反思
2016/02/23 职场文书
MYSQL(电话号码,身份证)数据脱敏的实现
2021/05/28 MySQL
使用jpa之动态插入与修改(重写save)
2021/11/23 Java/Android
MySQL解决Navicat设置默认字符串时的报错问题
2022/06/16 MySQL