Laravel中如何移除Eloquent数组匹配项以避免重复选项?
嘿,这个问题我之前也碰到过!你的嵌套循环之所以会重复生成选项,是因为每个服务都会和用户的每一个已购服务做对比——只要不匹配就输出一次,比如用户已经买了3个服务,那一个未购买的服务会被输出3次,自然就混乱了。
下面给你几个靠谱的解决方法,按推荐程度排序:
1. 最优方案:数据库层面直接过滤(性能最好)
这种方法直接在查询阶段就排除用户已经拥有的服务,不用在视图里做复杂逻辑,效率最高。
先在控制器里修改代码:
// 先获取当前用户已拥有的服务ID集合 $userOwnedServiceIds = \App\UserService::where('user_id', Auth::user()->id)->pluck('service_id'); // 查询所有不在已拥有ID列表里的服务 $availableServices = \App\Service::whereNotIn('id', $userOwnedServiceIds)->get();
然后在视图里直接循环这个过滤好的集合就行:
@foreach($availableServices as $service) <option value="{{ $service->id }}">{{ $service->name }}</option> @endforeach
2. 视图层面直接判断(适合快速调整)
如果不想改控制器逻辑,也可以在视图里先拿到用户已有的服务ID,然后逐个判断服务是否在列表里:
首先在控制器里把用户已有的服务ID传去视图:
$services = \App\Service::all(); $userOwnedServiceIds = \App\UserService::where('user_id', Auth::user()->id)->pluck('service_id'); // 把这两个变量都传给视图
然后视图里这样写:
@foreach($services as $service) {{-- 只输出用户未拥有的服务 --}} @if(!$userOwnedServiceIds->contains($service->id)) <option value="{{ $service->id }}">{{ $service->name }}</option> @endif @endforeach
这种方式每个服务只会判断一次,不会重复输出。
3. 用Eloquent集合的差集方法
如果你喜欢用集合操作,也可以直接求两个集合的差集:
控制器里:
$allServices = \App\Service::all(); // 获取用户已拥有的服务对应的Service模型集合 $userOwnedServices = $allServices->whereIn( 'id', \App\UserService::where('user_id', Auth::user()->id)->pluck('service_id') ); // 求差集,得到用户未拥有的服务 $availableServices = $allServices->diff($userOwnedServices);
然后视图里循环$availableServices就可以了,和第一种方法的视图代码一样。
总结一下,优先用第一种方法,因为数据库查询过滤比在PHP层面处理要高效得多,尤其是数据量比较大的时候。
内容的提问来源于stack exchange,提问作者Dip
相关产品推荐
相关产品推荐

