// products.php — Legacy monolithic controller
<?php
class ProductController {
public function getProducts($category) {
// N+1 Query Problem
$products = DB::query("SELECT * FROM products WHERE cat='$category'");
foreach ($products as $p) {
// Query in loop = N+1
$p->reviews = DB::query("SELECT * FROM reviews WHERE pid={$p->id}");
$p->stock = DB::query("SELECT qty FROM inventory WHERE pid={$p->id}");
// No caching
$p->recommendations = $this->getRecommendations($p->id);
}
// No pagination, loads ALL products
return view('products', ['products' => $products]);
}
private function getRecommendations($pid) {
// Hardcoded rules, no AI
return DB::query("SELECT * FROM products WHERE cat=(SELECT cat FROM products WHERE id=$pid) LIMIT 4");
}
}
// products_handler.go — Modern microservice with AI
package handlers
func (h *ProductHandler) GetProducts(c *fiber.Ctx) error {
category := c.Params("category")
page, limit := c.QueryInt("page", 1), c.QueryInt("limit", 20)
// Single optimized query with JOINs + pagination
products, err := h.repo.GetProductsWithDetails(category, page, limit)
// Redis cache layer (TTL: 5 min)
cached := h.cache.GetOrSet(cacheKey, 5*time.Minute, func() interface{} {
return products
})
// AI-powered recommendations (replaces hardcoded SQL)
userID := c.Locals("userID").(string)
recommendations := h.aiService.GetPersonalizedRecs(userID, category)
return c.JSON(fiber.Map{
"products": cached,
"recommendations": recommendations,
"pagination": fiber.Map{"page": page, "limit": limit},
})
}