Laravel事务报错后数据未回滚问题及原因解析
Laravel事务未回滚+「No morph map defined for model [App\Models\Order]」问题排查与解决
问题现象
- 采用两种Laravel事务写法(手动事务、闭包事务)执行时,均抛出
No morph map defined for model [App\Models\Order]错误 - 错误触发后,
Order::create()生成的数据并未被回滚,仍保留在数据库中
代码示例
1. 手动事务写法
\DB::beginTransaction(); try { $order = Order::create([ // 数据内容 ]); $order->notes()->create([ // 数据内容,此处会引发错误 ]); // 抛出错误:No morph map defined for model [App\Models\Order]. $order->transaction()->create([ // 数据内容 ]); } catch (\Exception $e) { \DB::rollBack(); return "error"; } \DB::commit(); return "success";
2. 闭包事务写法
\DB::transaction(function() use ($offer, $request) { $buyer = auth()->user(); $order = Order::create([ // 数据内容 ]); $order->notes()->create([ // 数据内容 ]); // 抛出错误:No morph map defined for model [App\Models\Order](因未定义模型别名) $order->transaction()->create([ // 数据内容 ]); }); return "success";
问题根源
- 事务无法回滚原因:Laravel默认数据库引擎配置为空,当前使用的是不支持事务的MyISAM引擎——MyISAM本身不支持事务机制,因此即便调用
rollBack(),已写入的数据也无法撤销。 - 多态关联错误原因:多态关联未定义模型别名,导致框架无法识别
App\Models\Order对应的多态类型标识。
解决步骤
1. 切换数据库引擎为InnoDB
- 修改
config/database.php中对应数据库连接的配置,指定引擎为InnoDB:'mysql' => [ // 其他配置项 'engine' => 'InnoDB', ], - 对已存在的表手动修改引擎:
ALTER TABLE orders ENGINE=InnoDB; ALTER TABLE notes ENGINE=InnoDB; ALTER TABLE transactions ENGINE=InnoDB; -- 对应transaction关联的表
2. 配置多态模型映射
在App\Providers\AppServiceProvider的boot()方法中添加多态映射,解决模型别名缺失问题:
use Illuminate\Database\Eloquent\Relations\Relation; public function boot() { Relation::morphMap([ 'order' => \App\Models\Order::class, // 可添加其他多态模型的映射关系 ]); }
内容的提问来源于stack exchange,提问作者Mahdi
相关产品推荐
相关产品推荐

