Laravel控制器嵌套foreach循环过滤受限海报生成新数组问题
Laravel国家受限海报过滤问题修复方案
现有代码问题
- 属性访问方式错误:Laravel中
DB::get()返回的是Collection集合,集合内的每一项是stdClass对象,无法通过数组下标$restrictedPoster['poster_viewable']的方式读取属性,需要用对象语法$restrictedPoster->poster_viewable访问。 - 过滤逻辑错误:嵌套循环没有匹配当前海报和受限海报的
poster_id,导致不管ID是否对应,只要受限列表中存在可查看的条目,就会把当前海报塞入结果数组,同时会出现同一张海报被重复添加的问题。
快速修复方案(基于现有代码调整)
先将受限海报转为ID为键、可视状态为值的映射表,再遍历全量海报做判断:
class PosterRestrictionController extends Controller { public function index() { $profile = app('App\Http\Controllers\DevelopmentController')->getActiveUser(Auth::id()); $userCountry = $profile->country; $unrestrictedPosters = []; $allPosters = DB::table('posters') ->join('profiles', 'posters.user_id', '=', 'profiles.user_id') ->join('users', 'posters.user_id', '=', 'users.id') ->select('users.name', 'profiles.surname', 'profiles.country', 'posters.id as poster_id', 'posters.user_id', 'posters.title', 'posters.category', ) ->orderBy('posters.id', 'asc') ->get(); $restrictedPosters = DB::table('posters') ->join('poster_restrictions', 'poster_restrictions.poster_id', '=', 'posters.id') ->where('poster_restrictions.restricted_country_id', '=', $userCountry) ->select( 'posters.id as poster_id', 'poster_restrictions.poster_viewable', 'poster_restrictions.restricted_country_id' ) ->orderBy('posters.id', 'asc') ->get(); // 生成受限海报ID和可视状态的映射表 $restrictedMap = $restrictedPosters->pluck('poster_viewable', 'poster_id'); foreach ($allPosters as $poster) { // 不在受限列表直接加入结果 if (!isset($restrictedMap[$poster->poster_id])) { $unrestrictedPosters[] = $poster; continue; } // 在受限列表且允许查看的才加入 if ($restrictedMap[$poster->poster_id] != 0) { $unrestrictedPosters[] = $poster; } } dd($unrestrictedPosters); //return view('你的模板名', compact('unrestrictedPosters')); } }
更优方案(单SQL查询,性能更高)
无需分两次查询再循环处理,直接通过左关联在数据库层面完成过滤:
public function index() { $profile = app('App\Http\Controllers\DevelopmentController')->getActiveUser(Auth::id()); $userCountry = $profile->country; $unrestrictedPosters = DB::table('posters') ->join('profiles', 'posters.user_id', '=', 'profiles.user_id') ->join('users', 'posters.user_id', '=', 'users.id') // 左关联对应当前国家的受限规则 ->leftJoin('poster_restrictions', function ($join) use ($userCountry) { $join->on('poster_restrictions.poster_id', '=', 'posters.id') ->where('poster_restrictions.restricted_country_id', '=', $userCountry); }) ->select('users.name', 'profiles.surname', 'profiles.country', 'posters.id as poster_id', 'posters.user_id', 'posters.title', 'posters.category', ) // 过滤条件:无受限规则 或 受限规则允许查看 ->where(function ($query) { $query->whereNull('poster_restrictions.id') ->orWhere('poster_restrictions.poster_viewable', '!=', 0); }) ->orderBy('posters.id', 'asc') ->get(); dd($unrestrictedPosters); }
内容的提问来源于stack exchange,提问作者BootDev
相关产品推荐
相关产品推荐

