带软删除的User模型使用子查询时遇列不存在错误的解决方法
我有如下查询和子查询代码:
// $query not included here $query = $query->getQuery(); $subQuery = User::select('*') ->fromSub($query, 'sub_query') ->where($status, 'LIKE', '%' . $statusValue . '%') ->with($this->eagerLoadedRelationships) ->get();
运行时出现错误:Column not found: 1054 Unknown column 'users.deleted_at' in 'where clause'。移除User模型中的use SoftDeletes;后能正常运行,但我需要保留软删除功能。尝试用User::withoutTrashed()->select('*')...,问题依旧。
限制条件:无法在select中列出具体列,且必须使用该子查询检查之前查询的结果(不能在之前的查询中添加where())。
问题根源是SoftDeletes trait会自动给User模型的所有查询加上where users.deleted_at is null的全局约束,但你用fromSub把前置查询作为子表sub_query后,当前查询的主体已经是这个子表,而非原users表,自动生成的deleted_at约束自然找不到users.deleted_at列。
给你两个可行的解决方案:
临时关闭软删除全局约束
直接移除SoftDeletes的全局作用域,让查询不再自动添加deleted_at相关条件,代码修改如下:$subQuery = User::withoutGlobalScope(\Illuminate\Database\Eloquent\SoftDeletingScope::class) ->select('*') ->fromSub($query, 'sub_query') ->where($status, 'LIKE', '%' . $statusValue . '%') ->with($this->eagerLoadedRelationships) ->get();这个方案最直接,完全适配你的限制条件,不需要改动前置查询逻辑。
调整软删除约束的表别名
如果子查询结果本身包含deleted_at列,你可以手动把自动生成的users.deleted_at替换为sub_query.deleted_at,不过需要通过自定义查询逻辑实现,相比第一种方案复杂度更高,优先推荐第一种。
补充说明:你之前用的withoutTrashed()无效,是因为这个方法只是明确查询未软删除的记录,但依然依赖原users表的deleted_at字段,而当前查询主体是子表,所以还是会触发列不存在的错误。
内容的提问来源于stack exchange,提问作者Tom Bom

