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 相关文章推荐
使用zend studio for eclipse不能激活代码提示功能的解决办法
Oct 11 PHP
Windows 下的 PHP-PEAR 安装方法
Nov 20 PHP
基于PHPExcel的常用方法总结
Jun 13 PHP
PHP URL参数获取方式的四种例子
Feb 28 PHP
PHP base64编码后解码乱码的解决办法
Jun 19 PHP
php中字符集转换iconv函数使用总结
Oct 11 PHP
PHP输出一个等腰三角形的方法
May 12 PHP
php简单计算年龄的方法(周岁与虚岁)
Dec 06 PHP
PHP实现深度优先搜索算法(DFS,Depth First Search)详解
Sep 16 PHP
PHP array_reduce()函数的应用解析
Oct 28 PHP
PHP数据对象映射模式实例分析
Mar 29 PHP
PHP中类与对象功能、用法实例解读
Mar 27 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
基于curl数据采集之单页面采集函数get_html的使用
2013/04/28 PHP
php字符串截取的简单方法
2013/07/04 PHP
php与c 实现按行读取文件实例代码
2017/01/03 PHP
告诉大家什么是JSON
2008/06/10 Javascript
推荐20家国外的脚本下载网站
2011/04/28 Javascript
javascript:;与javascript:void(0)使用介绍
2013/06/05 Javascript
自己写的Javascript计算时间差函数
2013/10/28 Javascript
js动态创建标签示例代码
2014/06/09 Javascript
js实现照片墙功能实例
2015/02/05 Javascript
理解js回收机制通俗易懂版
2016/02/29 Javascript
javascript使用闭包模拟对象的私有属性和方法
2016/10/05 Javascript
NodeJS遍历文件生产文件列表功能示例
2017/01/22 NodeJs
webpack入门+react环境配置
2017/02/08 Javascript
Angular directive递归实现目录树结构代码实例
2017/05/05 Javascript
nodejs 使用nodejs-websocket模块实现点对点实时通讯
2018/11/28 NodeJs
js实现视图和数据双向绑定的方法分析
2020/02/05 Javascript
vue-cli3 热更新配置操作
2020/09/18 Javascript
python制作花瓣网美女图片爬虫
2015/10/28 Python
python 实现二维列表转置
2019/12/02 Python
Flask项目中实现短信验证码和邮箱验证码功能
2019/12/05 Python
Python安装OpenCV的示例代码
2020/03/05 Python
Django操作session 的方法
2020/03/09 Python
Python偏函数实现原理及应用
2020/11/20 Python
使用JS+CSS3技术:让你的名字动起来
2013/04/27 HTML / CSS
意大利宠物用品购物网站:Bauzaar
2018/09/15 全球购物
Right-on官方网站:日本知名的休闲服装品牌
2019/07/12 全球购物
文员个人求职自荐信
2013/09/21 职场文书
服装机修工岗位职责
2013/12/26 职场文书
日语系毕业求职信
2014/07/27 职场文书
会计求职简历自我评价
2015/03/10 职场文书
施工单位工程部经理岗位职责
2015/04/09 职场文书
羊脂球读书笔记
2015/06/30 职场文书
商业计划书如何写?关键问题有哪些?
2019/07/11 职场文书
2019大学生社会实践报告汇总
2019/08/16 职场文书
gateway网关接口请求的校验方式
2021/07/15 Java/Android
vue中div禁止点击事件的实现
2022/04/02 Vue.js