Laravel 5.5销毁方法执行时SQL更新出现重复updated_at字段问题
updated_at字段的问题 Hey there, let's break down why that extra updated_at is appearing in your SQL query and fix it right away!
问题根源
你在更新valuechains关联数据时,手动指定了valuechains.updated_at字段,但Laravel的Eloquent模型默认会自动维护updated_at时间戳(只要模型的$timestamps属性为true,这是默认设置)。这就导致了重复:一个是你手动添加的带表前缀的valuechains.updated_at,另一个是Eloquent自动注入的不带表前缀的updated_at。
另外,既然你在设置deleted_at,说明Valuechain模型应该启用了软删除,其实Laravel已经为软删除提供了更简洁的处理方式,不用手动更新这些字段。
解决方案
方案1:移除手动指定的updated_at,让Eloquent自动处理
修改控制器中valuechains的更新代码,只设置deleted_at即可,Eloquent会自动帮你更新updated_at字段,并且会正确带上表前缀:
$sector->valuechains()->update([ 'deleted_at' => Carbon::now() ]);
方案2:直接使用软删除的delete()方法(更推荐)
如果你的Valuechain模型已经启用了软删除(也就是引入了SoftDeletes trait,并且在$dates中包含deleted_at),那么直接调用关联的delete()方法即可,Laravel会自动设置deleted_at和updated_at,完全不需要手动写update语句:
// 先确保Valuechain模型里有: // use Illuminate\Database\Eloquent\SoftDeletes; // protected $dates = ['created_at', 'updated_at', 'deleted_at']; $sector->valuechains()->delete();
额外优化:多对多中间表的软删除处理
你处理langs关联中间表的方式可以简化一下,不需要循环遍历ID,直接用updateExistingPivot的批量更新方式:
$sector->langs()->updateExistingPivot( $sector->langs()->allRelatedIds(), [ 'deleted_at' => Carbon::now(), 'updated_at' => Carbon::now() ] );
(注意:中间表lang_sector需要有deleted_at和updated_at字段,并且你可能需要手动处理中间表的软删除,因为Laravel默认不支持多对多中间表的软删除,除非自定义逻辑)
最终优化后的destroy方法
public function destroy($id) { $sector = Sector::findOrFail($id); // 更新多对多中间表的软删除字段 $sector->langs()->updateExistingPivot( $sector->langs()->allRelatedIds(), [ 'deleted_at' => Carbon::now(), 'updated_at' => Carbon::now() ] ); // 软删除关联的valuechains $sector->valuechains()->delete(); // 软删除当前sector $sector->delete(); }
这样修改后,生成的SQL就不会再出现重复的updated_at字段了,而且代码更简洁符合Laravel的最佳实践。
内容的提问来源于stack exchange,提问作者davidvera

