# 全自动事务 * * * * * **简介** 在 数据 > 事务控制 章节咱们讲解了 如何通过闭包控制事务,但是实际项目开发中存在一些问题就是咱们必须提前将需要处理事务的代码刻意封装在闭包中且对于复杂的业务流程中多处验证返回上会不是很便利,若一套较为复杂的业务逻辑(比如多个分散的类或文件中都进行了需要数据操作)这种情况可能导致循环执行事务也可能导致没有循环但是执行了多次事务(实际上还是无法有效的保证数据完整性)。 下面咱们再来分享一种事务控制的方式 ``` /** * 自动封装事务 */ function trans($parameter = [], $callback = null) { try { Db::startTrans(); $backtrace = debug_backtrace(false, 2); array_shift($backtrace); $class = $backtrace[0]['class']; $result = (new $class())->$callback($parameter); Db::commit(); return $result; } catch (Exception $ex) { Db::rollback(); throw new Exception($ex->getMessage()); } } ``` 这个函数用于将顶层的方法自动嵌套到事务处理中。 **使用方式** 控制器中: ``` // 测试事务 public function tranEvent() { return trans($this->param, 'tranTest'); } // 事务处理入口 public function tranTest($param = []) { dump($this->logicIndex->test($param)); } ``` 业务逻辑中: ``` /** * 测试操作 */ public function test($data = []) { $this->modelArticle->setInfo(['name' => '666'], ['id' => 23]); 1/0; //... 比如这里有多长很长的业务逻辑处理 //... 比如这里还执行了某文件里面的数据库操作 //... 比如这里执行了数据验证 比如 积分不足? 余额不足? 等操作 return [RESULT_SUCCESS, '操作成功']; } ``` **解决的问题** 1.面向切面的事务控制,若初期开发中业务逻辑层没有考虑到事务控制,那么后面想加入事务机制只需要在控制器中加一个类似于事件的方法中转即可,业务层的代码基本上不需要改动。 2.避免了业务流程复杂时 循环执行事务及多个事务分散在各处无法保证多个事务都OK的情况。 3.清爽的代码将控制器中四处可见的 try catch 消灭掉。 4.有效提升了开发效率,开发者在编写业务逻辑时无需考虑数据完整性问题。 5.有效控制事务的同时也与OneBase目前返回跳转及提示机制完美兼容,不知不觉已经在所有的代码上自动加上了事务控制。