feat: Implement product listing API with caching , sorting , filters and search

- Add ProductController with index method to provide product listings
- Implement caching for product listings based on request URI
- Add sorting functionality for products by various criteria (new, old, most_view, less_view, most_buy, less_buy)
- Implement filtering by category using slug
- Add search functionality to filter products by name
- Implement price range filtering using min_price and max_price parameters
- Include related category data in the product resource response
- Set default pagination to 20 items per page with optional customization via per_page parameter
pull/45/head
cyberali 2 months ago
parent a8099343ad
commit dcead2a865

@ -0,0 +1,63 @@
<?php
namespace App\Http\Controllers\Api\Web;
use App\Http\Controllers\Controller;
use App\Http\Resources\ProductResource;
use App\Models\Category;
use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class ProductController extends Controller
{
public function index(Request $request)
{
$cacheKey = 'products_' . md5($request->getUri());
$data = Cache::remember($cacheKey, now()->addMinutes(env('CACHE_LIFE_TIME', 10)), function () use ($request) {
$product = Product::query();
/**
* Product Sort by keys
*/
if (isset($request['sort']) && !is_null($request['sort'])) {
if ($request['sort'] === 'new')
$product = $product->orderByDesc('created_at');
if ($request['sort'] === 'old')
$product = $product->orderBy('created_at');
if ($request['sort'] === 'most_view')
$product = $product->orderByDesc('view');
if ($request['sort'] === 'less_view')
$product = $product->orderBy('view');
if ($request['sort'] === 'most_buy')
$product = $product->orderByDesc('sell');
if ($request['sort'] === 'less_buy')
$product = $product->orderBy('sell');
}
if (isset($request['category']) && !is_null($request['category']))
$product = $product->where('category_id', Category::firstWhere('slug', $request['category'])->id);
if (isset($request['search']) && !is_null($request['search']))
$product = $product->where('name', 'LIKE', "%$request->search%");
if (isset($request['min_price']) &&
isset($request['max_price']) &&
!is_null($request['min_price']) &&
!is_null($request['max_price'])
) {
$product = $product->whereBetween('buy_price', [
intval($request->min_price),
intval($request->max_price)
]);
}
$request->merge([
'loadCategory' => true
]);
return [
'products' => ProductResource::collection($product->paginate($request->input('per_page', 20)))->resource->toArray(),
];
});
return success($data);
}
}

@ -21,6 +21,8 @@ class CategoryResource extends JsonResource
/** /**
* @var $this Category * @var $this Category
*/ */
if (!$request['loadCategory'])
$request->merge([ $request->merge([
'loadCategory' => false 'loadCategory' => false
]); ]);
@ -33,7 +35,7 @@ class CategoryResource extends JsonResource
'sort' => $this->sort, 'sort' => $this->sort,
'image' => $this->image, 'image' => $this->image,
'bg' => $this->bg, 'bg' => $this->bg,
'products' => $this->when($request->input('loadProduct' , true) , ProductResource::collection($this->products)->additional(['request' => $request['loadCategory']]) ) 'products' => $this->when($request->input('loadProduct', true), ProductResource::collection($this->products)->additional(['request' => $request['loadCategory']]))
]; ];
} }
} }

@ -18,22 +18,26 @@ class ProductResource extends JsonResource
/** /**
* @var $this Product * @var $this Product
*/ */
if (!$request['loadProduct'])
$request->merge([ $request->merge([
'loadProduct' => false 'loadProduct' => false
]); ]);
return [ return [
'id' => $this->id, 'id' => $this->id,
'name' => $this->name,
'slug' => $this->slug, 'slug' => $this->slug,
'description' => $this->description, 'description' => $this->description,
'table' => $this->table, 'table' => $this->table,
'sku' => $this->sku, 'sku' => $this->sku,
'virtual' => $this->virtual, 'virtual' => $this->virtual,
'downloadable' => $this->downloadable, 'downloadable' => $this->downloadable,
'price' => $this->price, 'price' => intval($this->price),
'buy_price' => $this->buy_price, 'buy_price' => $this->buy_price,
'average_rating' => $this->average_rating, 'average_rating' => floatval($this->average_rating),
'view' => $this->view, 'view' => $this->view,
'category' => $this->when($request->input('loadCategory', true), new CategoryResource($this->category)) 'category' => $this->when($request->input('loadCategory', true), new CategoryResource($this->category)),
'image' => $this->imgUrl()
]; ];
} }
} }

@ -40,4 +40,5 @@ Route::prefix('v1')->name('v1.')->group(
Route::post('visitor/display', [\App\Http\Controllers\Api\VisitorController::class, 'display'])->name('visitor.display'); Route::post('visitor/display', [\App\Http\Controllers\Api\VisitorController::class, 'display'])->name('visitor.display');
Route::apiResource('web', \App\Http\Controllers\Api\Web\HomeController::class)->only('index'); Route::apiResource('web', \App\Http\Controllers\Api\Web\HomeController::class)->only('index');
Route::apiResource('products' , \App\Http\Controllers\Api\Web\ProductController::class)->only('index');
}); });

Loading…
Cancel
Save