You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何保持响应结构并完成数据去重与指定条目移除?

问题分析与解决方案

问题原因

你当前的问题核心在于:

  1. 对ScreenCollection实例直接调用filter和unique后,返回的是普通Collection对象,不再是自定义的ScreenCollection,因此不会执行toArray方法里的字段映射逻辑,导致返回的是模型原始字段(比如id、status_id),结构不符合预期。
  2. unique方法会保留集合的原始键名,转成JSON时会变成带键的对象,而非预期的数组结构。

解决方案

方案一:数据库查询阶段直接过滤(推荐,性能更优)

直接在查询时排除不需要的数据并完成去重,减少后续内存处理的成本:

public function homeScreenData()
{
    $menus = $this->appScreen->query()
        ->where('status_id', 1)
        ->whereNotIn('name', ['book', 'pc']) // 移除name为book、pc的条目
        ->when(!hasPermission('report'), function ($query) {
            return $query->where('slug', '!=', 'report');
        })
        ->distinct('name') // 按name字段去重
        ->orderBy('position', 'ASC')
        ->get();

    $data = new ScreenCollection($menus);
    return $this->responseWithSuccess('App home screen menus', $data, 200);
}

方案二:集合层面处理后重新包装为ScreenCollection

如果必须在内存中处理集合,先处理原始Eloquent集合,再传给自定义集合,同时用values()重置键为连续索引:

public function homeScreenData()
{
    $menus = $this->appScreen->query()->where('status_id', 1)->orderBy('position', 'ASC')
        ->when(!hasPermission('report'), function ($query) {
            return $query->where('slug', '!=', 'report');
        })
        ->get();

    // 先过滤、去重,再重置键为连续数组索引
    $filteredMenus = $menus->filter(function($item){
        return $item->name != 'book' && $item->name != 'pc';
    })->unique('name')->values();

    $data = new ScreenCollection($filteredMenus);
    return $this->responseWithSuccess('App home screen menus', $data, 200);
}

方案三:将逻辑封装到ScreenCollection内部

把过滤和去重逻辑放到自定义集合的toArray方法里,让集合自身处理数据,Controller代码更简洁:

修改ScreenCollection

public function toArray($request)
{
    $processedData = $this->collection
        ->filter(function ($data) {
            // 移除book、pc条目
            return $data->name != 'book' && $data->name != 'pc';
        })
        ->unique('name') // 按name去重
        ->values() // 重置键为数组索引,保证JSON结构正确
        ->map(function ($data) {
            return [
                'name' => $data->name,
                'slug' => $data->slug,
                'position' => (int) $data->position,
                'icon' => my_asset($data->icon)
            ];
        });

    return [
        'data' => $processedData
    ];
}

Controller代码无需额外处理

public function homeScreenData()
{
    $menus = $this->appScreen->query()->where('status_id', 1)->orderBy('position', 'ASC')
        ->when(!hasPermission('report'), function ($query) {
            return $query->where('slug', '!=', 'report');
        })
        ->get();

    $data = new ScreenCollection($menus);
    return $this->responseWithSuccess('App home screen menus', $data, 200);
}

内容的提问来源于stack exchange,提问作者sai sa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 02:24:29