File manager - Edit - /home/webapp69.cm.in.th/u69319090039/Shop39/app/Controllers/ProductController.php
Back
<?php class ProductController extends Controller { public function index(): void { $productModel = new Product(); $categoryModel = new Category(); // Get raw query — avoid FILTER_SANITIZE_FULL_SPECIAL_CHARS which encodes % and breaks LIKE $query = trim(strip_tags($_GET['q'] ?? '')); $categoryId = isset($_GET['category']) ? (int)$_GET['category'] : 0; $sort = trim(strip_tags($_GET['sort'] ?? 'latest')); // Build filtering SQL dynamically $where = ["p.status = 'active'"]; $params = []; if (!empty($query)) { // Escape SQL LIKE wildcards so literal % and _ in search terms work correctly $escaped = addcslashes($query, '%_'); $where[] = "(p.title LIKE :query1 OR p.description LIKE :query2 OR p.slug LIKE :query3)"; $params['query1'] = "%{$escaped}%"; $params['query2'] = "%{$escaped}%"; $params['query3'] = "%{$escaped}%"; } if ($categoryId > 0) { $where[] = "p.category_id = :cat_id"; $params['cat_id'] = $categoryId; } $whereSql = implode(' AND ', $where); if ($sort === 'price_asc') { $orderSql = 'p.price ASC'; } elseif ($sort === 'price_desc') { $orderSql = 'p.price DESC'; } else { $orderSql = 'p.id DESC'; } $sql = "SELECT p.*, c.name AS category_name, sp.shop_name, sp.slug AS shop_slug, (SELECT image_path FROM product_images WHERE product_id = p.id AND is_primary = 1 LIMIT 1) AS primary_image FROM products p JOIN categories c ON p.category_id = c.id JOIN seller_profiles sp ON p.seller_id = sp.id WHERE {$whereSql} AND sp.status = 'approved' AND sp.deleted_at IS NULL ORDER BY {$orderSql}"; $db = Database::getInstance(); $stmt = $db->prepare($sql); $stmt->execute($params); $products = $stmt->fetchAll(); $this->render('products/index', [ 'title' => 'สินค้าทั้งหมด', 'products' => $products, 'categories' => $categoryModel->getActiveCategories(), 'currentCat' => $categoryId, 'query' => $query, 'sort' => $sort ]); } public function detail(string $slug): void { $productModel = new Product(); $product = $productModel->getProductWithDetails($slug); if (!$product) { http_response_code(404); require_once SITE_ROOT . '/app/Views/errors/404.php'; exit; } // Verify if the seller is active/approved $db = Database::getInstance(); $stCheck = $db->prepare("SELECT status, deleted_at FROM seller_profiles WHERE id = :sid LIMIT 1"); $stCheck->execute(['sid' => $product['seller_id']]); $sellerProfileData = $stCheck->fetch(); if (!$sellerProfileData || $sellerProfileData['status'] !== 'approved' || $sellerProfileData['deleted_at'] !== null) { http_response_code(404); require_once SITE_ROOT . '/app/Views/errors/404.php'; exit; } $reviewModel = new Review(); $reviews = $reviewModel->getApprovedProductReviews((int)$product['id']); $ratingMetrics = $reviewModel->getProductRatingMetrics((int)$product['id']); $this->render('products/detail', [ 'title' => $product['title'], 'product' => $product, 'reviews' => $reviews, 'ratingMetrics' => $ratingMetrics ]); } public function storeFront(string $slug): void { $db = Database::getInstance(); // Get seller profile $stmt = $db->prepare("SELECT sp.*, u.full_name, u.email FROM seller_profiles sp JOIN users u ON sp.user_id = u.id WHERE sp.slug = :slug AND sp.status = 'approved' LIMIT 1"); $stmt->execute(['slug' => $slug]); $seller = $stmt->fetch(); if (!$seller) { http_response_code(404); require_once SITE_ROOT . '/app/Views/errors/404.php'; exit; } // Get seller products // Get raw query $query = trim(strip_tags($_GET['q'] ?? '')); $sort = trim(strip_tags($_GET['sort'] ?? 'latest')); $where = ["p.seller_id = :sid", "p.status = 'active'"]; $params = ['sid' => $seller['id']]; if (!empty($query)) { $escaped = addcslashes($query, '%_'); $where[] = "(p.title LIKE :query1 OR p.description LIKE :query2)"; $params['query1'] = "%{$escaped}%"; $params['query2'] = "%{$escaped}%"; } $whereSql = implode(' AND ', $where); if ($sort === 'price_asc') { $orderSql = 'p.price ASC'; } elseif ($sort === 'price_desc') { $orderSql = 'p.price DESC'; } else { $orderSql = 'p.id DESC'; } $prodSql = "SELECT p.*, c.name AS category_name, (SELECT image_path FROM product_images WHERE product_id = p.id AND is_primary = 1 LIMIT 1) AS primary_image FROM products p JOIN categories c ON p.category_id = c.id WHERE {$whereSql} ORDER BY {$orderSql}"; $prodStmt = $db->prepare($prodSql); $prodStmt->execute($params); $products = $prodStmt->fetchAll(); // Check if current logged-in user is the owner of this shop $currentUser = Auth::user(); $isOwner = $currentUser && ((int)$currentUser['id'] === (int)$seller['user_id']); $this->render('store/show', [ 'title' => $seller['shop_name'] . ' - หน้าร้านค้า', 'seller' => $seller, 'products' => $products, 'isOwner' => $isOwner, 'query' => $query, 'sort' => $sort ]); } /** * API endpoint: GET /api/search-suggest?q=keyword * Returns JSON array of up to 8 matching products for autocomplete */ public function searchSuggest(): void { header('Content-Type: application/json; charset=utf-8'); header('X-Content-Type-Options: nosniff'); $q = trim(strip_tags($_GET['q'] ?? '')); if (mb_strlen($q) < 1) { echo json_encode([]); exit; } // Escape SQL LIKE wildcards $escaped = addcslashes($q, '%_'); $db = Database::getInstance(); $sql = "SELECT p.slug, p.title, p.price, p.sale_price, sp.shop_name, (SELECT image_path FROM product_images WHERE product_id = p.id AND is_primary = 1 LIMIT 1) AS primary_image FROM products p JOIN seller_profiles sp ON p.seller_id = sp.id WHERE p.status = 'active' AND (p.title LIKE :q1 OR p.description LIKE :q2 OR p.slug LIKE :q3) ORDER BY p.id DESC LIMIT 8"; $stmt = $db->prepare($sql); $stmt->execute(['q1' => "%{$escaped}%", 'q2' => "%{$escaped}%", 'q3' => "%{$escaped}%"]); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); $results = []; foreach ($rows as $row) { $imgPath = !empty($row['primary_image']) ? APP_URL . '/public/' . ltrim($row['primary_image'], '/') : APP_URL . '/public/assets/images/sample-headphone.jpg'; $displayPrice = !empty($row['sale_price']) ? (float)$row['sale_price'] : (float)$row['price']; $results[] = [ 'slug' => $row['slug'], 'title' => $row['title'], 'price' => number_format($displayPrice, 2), 'shop_name' => $row['shop_name'], 'image' => $imgPath, 'url' => APP_URL . '/product/' . $row['slug'], ]; } echo json_encode($results, JSON_UNESCAPED_UNICODE); exit; } /** * Categories Listing Page: GET /categories */ public function categories(): void { $categoryModel = new Category(); $db = Database::getInstance(); // Fetch active categories with product counts $sql = "SELECT c.*, (SELECT COUNT(p.id) FROM products p JOIN seller_profiles sp ON p.seller_id = sp.id WHERE p.category_id = c.id AND p.status = 'active' AND sp.status = 'approved' AND sp.deleted_at IS NULL) AS product_count FROM categories c WHERE c.status = 'active' ORDER BY c.id ASC"; $stmt = $db->prepare($sql); $stmt->execute(); $categories = $stmt->fetchAll(); $this->render('products/categories', [ 'title' => 'หมวดหมู่สินค้าทั้งหมด', 'categories' => $categories ]); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.22 |
proxy
|
phpinfo
|
Settings