如何简化给定Laravel代码,并在Laravel Collection中添加自定义字段?
简化代码并通过Laravel Collection添加自定义字段
优化方案(解决N+1查询问题)
原代码存在N+1查询问题(每个Location都单独执行一次Book查询),推荐用Eloquent的withCount直接统计,再通过Collection的map方法转换结构并添加自定义字段:
$locations = Location::query() ->withCount([ 'books' => fn ($query) => $query->where('title', 'LIKE', "%{$keyword}%") ]) ->get() ->map(function ($location) { return [ 'id' => $location->id, 'code' => $location->code, 'name' => $location->name, 'count' => $location->books_count, // 示例:通过if-else逻辑添加自定义字段 'is_popular' => $location->books_count >= 10 ? true : false, // 示例:通过关联预加载添加字段(避免额外查询) 'latest_book' => $location->books()->latest()->first()?->title ]; });
关键说明
- 避免N+1查询:
withCount会在查询Location时,一次性统计每个Location下符合条件的Book数量,生成books_count属性,比循环查询效率高得多。 - Collection添加字段:用
map方法遍历集合中的每个Location模型,返回新的数组结构,同时可以添加需要的自定义字段——不管是简单的if-else逻辑,还是基于关联的额外数据(尽量用预加载替代单独查询)。
若需保留循环查询场景(不推荐)
如果因为特殊需求必须单独处理每个Location的查询,也可以直接用Collection简化原代码:
$locations = Location::all() ->map(function ($l) use ($keyword) { $count = Book::where('title', 'LIKE', "%{$keyword}%") ->where('location_id', $l->id) ->count(); return [ 'id' => $l->id, 'code' => $l->code, 'name' => $l->name, 'count' => $count, // 自定义字段示例:多分支逻辑 'count_label' => match(true) { $count > 20 => '大量', $count > 5 => '中等', default => '少量' } ]; });
核心简化点
原代码手动构建$dataLocation数组再转Collection,直接用map方法可以一步完成遍历、字段转换和自定义字段添加,代码更简洁流畅。
内容的提问来源于stack exchange,提问作者Kristian Juri Damai Lase
相关产品推荐
相关产品推荐

