Laravel按分类及含子级位置检索Listing的实现问题
解决方案:Laravel中分类与位置的层级筛选优化
1. 模型层添加层级ID获取方法
首先在Category和Location模型中实现递归获取所有子级ID的方法,确保选中父节点时能包含所有下级节点的数据。
Category模型代码:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Category extends Model { // 原有的childrenRecursive关联 public function childrenRecursive() { return $this->children()->with('childrenRecursive', 'rListing'); } // 递归获取当前分类及其所有子级的ID private function getAllCategoryIds() { $ids = [$this->id]; foreach ($this->childrenRecursive as $child) { $ids = array_merge($ids, $child->getAllCategoryIds()); } return $ids; } // 静态方法:通过分类ID获取全层级ID集合 public static function getHierarchyIds($categoryId) { $category = self::find($categoryId); return $category ? $category->getAllCategoryIds() : []; } }
Location模型代码:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Location extends Model { // 原有的childrenRecursive关联 public function childrenRecursive() { return $this->children()->with('childrenRecursive', 'rListing'); } // 递归获取当前位置及其所有子级的ID private function getAllLocationIds() { $ids = [$this->id]; foreach ($this->childrenRecursive as $child) { $ids = array_merge($ids, $child->getAllLocationIds()); } return $ids; } // 静态方法:通过位置ID获取全层级ID集合 public static function getHierarchyIds($locationId) { $location = self::find($locationId); return $location ? $location->getAllLocationIds() : []; } }
2. 控制器查询逻辑优化
修改原有的查询代码,使用whereIn替代单一ID匹配,传入全层级ID集合实现批量筛选:
// 初始化查询,提前关联必要表并添加固定条件 $listing_items = DB::table('listings') ->join('listing_categories', 'listings.listing_category_id', '=', 'listing_categories.id') ->join('listing_locations', 'listings.listing_location_id', '=', 'listing_locations.id') ->where('listings.listing_status', 'Active'); // 关键词模糊筛选 if ($request->filled('text')) { $listing_items->where('listings.listing_name', 'LIKE', '%' . $request->text . '%'); } // 分类层级筛选 if ($request->filled('category')) { $categoryIds = \App\Models\Category::getHierarchyIds($request->category); if (!empty($categoryIds)) { $listing_items->whereIn('listings.listing_category_id', $categoryIds); } } // 位置层级筛选 if ($request->filled('location')) { $locationIds = \App\Models\Location::getHierarchyIds($request->location); if (!empty($locationIds)) { $listing_items->whereIn('listings.listing_location_id', $locationIds); } } // 选择字段并分页返回 $listing_items = $listing_items->select( 'listings.*', 'listing_categories.listing_category_name', 'listing_categories.listing_category_slug', 'listing_locations.listing_location_name', 'listing_locations.listing_location_slug' )->paginate(4);
3. 性能优化建议(针对大数据量)
如果你的分类/位置层级较深或数据量较大,递归模型方法可能存在性能瓶颈,建议使用数据库原生递归查询(以MySQL为例):
修改模型中的getHierarchyIds方法为:
public static function getHierarchyIds($categoryId) { $ids = DB::select(" WITH RECURSIVE category_hierarchy AS ( SELECT id FROM categories WHERE id = ? UNION ALL SELECT c.id FROM categories c JOIN category_hierarchy ch ON c.parent_id = ch.id ) SELECT id FROM category_hierarchy ", [$categoryId]); return array_column($ids, 'id'); }
该方法通过数据库的WITH RECURSIVE语法一次性获取所有层级ID,性能更优。
内容的提问来源于stack exchange,提问作者Tajmmal Hussan
相关产品推荐
相关产品推荐

