1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| <?php
namespace App\Repositories\Eloquent;
use App\Models\Product; use App\Repositories\BaseRepository; use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection;
class ProductRepository extends BaseRepository { protected array $allowedFilters = [ 'category', 'brand', 'price_min', 'price_max', 'in_stock', 'sort', ];
public function __construct(Product $model) { parent::__construct($model); }
public function filter(array $filters, int $perPage = 15): LengthAwarePaginator { $query = $this->newQuery()->with(['category', 'brand']);
if (isset($filters['category'])) { $query->where('category_id', $filters['category']); }
if (isset($filters['brand'])) { $query->where('brand_id', $filters['brand']); }
if (isset($filters['price_min'])) { $query->where('price', '>=', $filters['price_min']); }
if (isset($filters['price_max'])) { $query->where('price', '<=', $filters['price_max']); }
if (isset($filters['in_stock']) && $filters['in_stock']) { $query->where('stock', '>', 0); }
if (isset($filters['sort'])) { $query = $this->applySort($query, $filters['sort']); }
return $query->paginate($perPage); }
protected function applySort($query, string $sort) { $sortMap = [ 'price_asc' => ['price', 'asc'], 'price_desc' => ['price', 'desc'], 'name_asc' => ['name', 'asc'], 'name_desc' => ['name', 'desc'], 'newest' => ['created_at', 'desc'], ];
if (isset($sortMap[$sort])) { [$column, $direction] = $sortMap[$sort]; return $query->orderBy($column, $direction); }
return $query->orderBy('created_at', 'desc'); }
public function findFeatured(): Collection { return $this->model ->where('is_featured', true) ->where('is_active', true) ->orderBy('featured_at', 'desc') ->get(); }
public function findRelated(int $productId, int $limit = 4): Collection { $product = $this->find($productId);
if (!$product) { return collect(); }
return $this->model ->where('category_id', $product->category_id) ->where('id', '!=', $productId) ->limit($limit) ->get(); }
public function search(string $query, int $perPage = 15): LengthAwarePaginator { return $this->model ->where(function ($q) use ($query) { $q->where('name', 'like', "%{$query}%") ->orWhere('description', 'like', "%{$query}%") ->orWhere('sku', 'like', "%{$query}%"); }) ->paginate($perPage); } }
|