File manager - Edit - /home/webapp69.cm.in.th/u69319090034/Shop 034/api.php
Back
<?php // API ตัวกลางจัดการข้อมูลแบบ JSON (api.php) require_once 'auth.php'; require_once 'config.php'; header('Content-Type: application/json; charset=utf-8'); $action = $_GET['action'] ?? ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { // อ่านข้อมูล JSON input $inputData = json_decode(file_get_contents('php://input'), true); } switch ($action) { // 1. ดึงรายละเอียดของสินค้าเฉพาะ Variant (เช่น ราคาพิเศษ สต็อก ตามคู่สีและไซซ์) case 'get_variant': $productId = intval($_GET['product_id'] ?? 0); $colorId = intval($_GET['color_id'] ?? 0); $sizeId = intval($_GET['size_id'] ?? 0); if (!$productId || !$colorId || !$sizeId) { echo json_encode(['success' => false, 'message' => 'ข้อมูลไม่ครบถ้วน']); exit; } try { // ดึง Variant ที่ผูกกับ Attribute values ทั้งสองตัว $stmt = $conn->prepare(" SELECT pv.* FROM product_variants pv JOIN variant_option_values vov1 ON pv.id = vov1.variant_id JOIN variant_option_values vov2 ON pv.id = vov2.variant_id WHERE pv.product_id = :product_id AND vov1.attribute_value_id = :color_id AND vov2.attribute_value_id = :size_id LIMIT 1 "); $stmt->execute([ ':product_id' => $productId, ':color_id' => $colorId, ':size_id' => $sizeId ]); $variant = $stmt->fetch(); if ($variant) { echo json_encode(['success' => true, 'variant' => $variant]); } else { echo json_encode(['success' => false, 'message' => 'ไม่พบสินค้าย่อยที่ระบุ']); } } catch (PDOException $e) { echo json_encode(['success' => false, 'message' => $e->getMessage()]); } break; // 2. เพิ่มสินค้าเข้าตะกร้า case 'add_to_cart': if (!isset($inputData['variant_id']) || !isset($inputData['quantity'])) { echo json_encode(['success' => false, 'message' => 'ข้อมูลไม่ถูกต้อง']); exit; } $variantId = intval($inputData['variant_id']); $quantity = intval($inputData['quantity']); try { // เช็คสต็อกจริงจากฐานข้อมูล $stmt = $conn->prepare(" SELECT pv.*, p.name as product_name, p.base_price FROM product_variants pv JOIN products p ON pv.product_id = p.id WHERE pv.id = :variant_id "); $stmt->execute([':variant_id' => $variantId]); $variant = $stmt->fetch(); if (!$variant) { echo json_encode(['success' => false, 'message' => 'ไม่พบสินค้า']); exit; } if ($variant['stock_quantity'] < $quantity) { echo json_encode(['success' => false, 'message' => 'ขออภัย สต็อกมีไม่เพียงพอ']); exit; } // ดึงข้อมูล option (สี/ไซซ์) ของ variant นี้ $stmtOpt = $conn->prepare(" SELECT a.name as attr_name, av.value as attr_value FROM variant_option_values vov JOIN attribute_values av ON vov.attribute_value_id = av.id JOIN attributes a ON av.attribute_id = a.id WHERE vov.variant_id = :variant_id "); $stmtOpt->execute([':variant_id' => $variantId]); $options = $stmtOpt->fetchAll(); $variantDetails = []; foreach ($options as $opt) { $variantDetails[$opt['attr_name']] = $opt['attr_value']; } // ค้นหารูปภาพที่เชื่อมกับสีนี้ หรือรูปภาพแรกของสินค้า $colorValId = null; // หา color value id ใน variant นี้ $stmtColorVal = $conn->prepare(" SELECT attribute_value_id FROM variant_option_values vov JOIN attribute_values av ON vov.attribute_value_id = av.id WHERE vov.variant_id = :variant_id AND av.attribute_id = 1 LIMIT 1 "); $stmtColorVal->execute([':variant_id' => $variantId]); $colorVal = $stmtColorVal->fetch(); if ($colorVal) { $colorValId = $colorVal['attribute_value_id']; } // ดึงรูปที่ผูกสี หรือรูปหลัก $stmtImg = $conn->prepare(" SELECT image_url FROM product_images WHERE product_id = :product_id AND (color_attribute_value_id = :color_val OR color_attribute_value_id IS NULL) ORDER BY color_attribute_value_id DESC, is_main DESC, sort_order ASC LIMIT 1 "); $stmtImg->execute([ ':product_id' => $variant['product_id'], ':color_val' => $colorValId ]); $img = $stmtImg->fetch(); $imageUrl = $img ? $img['image_url'] : 'https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=200'; // สร้างหรือบันทึกลง Session Cart if (!isset($_SESSION['cart'])) { $_SESSION['cart'] = []; } // ถ้ามีสินค้าชิ้นนี้อยู่แล้ว ให้บวกจำนวนเพิ่ม $cartKey = 'v_' . $variantId; if (isset($_SESSION['cart'][$cartKey])) { $newQty = $_SESSION['cart'][$cartKey]['qty'] + $quantity; if ($variant['stock_quantity'] < $newQty) { echo json_encode(['success' => false, 'message' => 'ขออภัย คุณมีสินค้าชิ้นนี้ในตะกร้าจนเต็มจำนวนสต็อกแล้ว']); exit; } $_SESSION['cart'][$cartKey]['qty'] = $newQty; } else { $_SESSION['cart'][$cartKey] = [ 'variant_id' => $variantId, 'product_id' => $variant['product_id'], 'name' => $variant['product_name'], 'price' => floatval($variant['base_price']) + floatval($variant['price_modifier']), 'qty' => $quantity, 'sku' => $variant['sku'], 'image' => $imageUrl, 'details' => $variantDetails ]; } $totalCount = 0; foreach ($_SESSION['cart'] as $item) { $totalCount += $item['qty']; } echo json_encode(['success' => true, 'total_count' => $totalCount]); } catch (PDOException $e) { echo json_encode(['success' => false, 'message' => $e->getMessage()]); } break; // 3. ลบสินค้าออกจากตะกร้า case 'remove_from_cart': if (!isset($inputData['cart_key'])) { echo json_encode(['success' => false, 'message' => 'ข้อมูลไม่ถูกต้อง']); exit; } $cartKey = $inputData['cart_key']; if (isset($_SESSION['cart'][$cartKey])) { unset($_SESSION['cart'][$cartKey]); $totalCount = 0; $totalAmount = 0; foreach ($_SESSION['cart'] as $item) { $totalCount += $item['qty']; $totalAmount += ($item['price'] * $item['qty']); } echo json_encode([ 'success' => true, 'total_count' => $totalCount, 'total_amount' => $totalAmount ]); } else { echo json_encode(['success' => false, 'message' => 'ไม่พบสินค้านี้ในตะกร้า']); } break; // 4. สั่งซื้อสินค้าชำระเงิน (Checkout) case 'checkout': if (empty($_SESSION['cart'])) { echo json_encode(['success' => false, 'message' => 'ไม่มีสินค้าในตะกร้า']); exit; } if (empty($inputData['customer_name']) || empty($inputData['shipping_address'])) { echo json_encode(['success' => false, 'message' => 'กรุณากรอกชื่อและที่อยู่จัดส่งให้ครบถ้วน']); exit; } try { $conn->beginTransaction(); $totalAmount = 0; foreach ($_SESSION['cart'] as $item) { $totalAmount += ($item['price'] * $item['qty']); } // 4.1 สร้างแถว Order $stmtOrder = $conn->prepare(" INSERT INTO orders (customer_name, shipping_address, total_amount, status) VALUES (:name, :address, :amount, 'pending') "); $stmtOrder->execute([ ':name' => $inputData['customer_name'], ':address' => $inputData['shipping_address'], ':amount' => $totalAmount ]); $orderId = $conn->lastInsertId(); // 4.2 วนลูปบันทึก Order Items และตัดสต็อก foreach ($_SESSION['cart'] as $item) { // เช็คสต็อกอีกครั้งด้วย SELECT ... FOR UPDATE ป้องกัน Race Condition $stmtCheck = $conn->prepare(" SELECT stock_quantity FROM product_variants WHERE id = :id FOR UPDATE "); $stmtCheck->execute([':id' => $item['variant_id']]); $currentStock = $stmtCheck->fetchColumn(); if ($currentStock < $item['qty']) { throw new Exception("ขออภัย สินค้า " . $item['name'] . " (" . implode(', ', $item['details']) . ") สต็อกไม่เพียงพอสำหรับการสั่งซื้อ"); } // ตัดสต็อก $stmtDeduct = $conn->prepare(" UPDATE product_variants SET stock_quantity = stock_quantity - :qty WHERE id = :id "); $stmtDeduct->execute([ ':qty' => $item['qty'], ':id' => $item['variant_id'] ]); // บันทึก Order item (จัดเก็บรายละเอียด สี ไซซ์ ลง JSON) $stmtItem = $conn->prepare(" INSERT INTO order_items (order_id, product_variant_id, quantity, price, product_name, variant_details) VALUES (:order_id, :variant_id, :qty, :price, :name, :details) "); $stmtItem->execute([ ':order_id' => $orderId, ':variant_id' => $item['variant_id'], ':qty' => $item['qty'], ':price' => $item['price'], ':name' => $item['name'], ':details' => json_encode($item['details'], JSON_UNESCAPED_UNICODE) ]); } $conn->commit(); // เคลียร์ตะกร้าสินค้า $_SESSION['cart'] = []; echo json_encode(['success' => true, 'order_id' => $orderId]); } catch (Exception $e) { $conn->rollBack(); echo json_encode(['success' => false, 'message' => $e->getMessage()]); } break; // 5. หลังบ้าน - บันทึกสร้างสินค้าใหม่พร้อมตาราง Variant Matrix case 'admin_create_product': if (!isSellerLoggedIn()) { echo json_encode(['success' => false, 'message' => 'ไม่มีสิทธิ์ในการดำเนินการ (Unauthorized) กรุณาเข้าสู่ระบบ']); exit; } if (empty($inputData['name']) || empty($inputData['base_price'])) { echo json_encode(['success' => false, 'message' => 'กรุณากรอกชื่อสินค้าและราคาเริ่มต้น']); exit; } try { $conn->beginTransaction(); // 5.1 บันทึกข้อมูลตารางสินค้าหลัก $stmtProd = $conn->prepare(" INSERT INTO products (name, description, base_price, category_id, size_chart_id, seller_id, status) VALUES (:name, :desc, :price, :cat_id, :chart_id, :seller_id, 'active') "); $stmtProd->execute([ ':name' => $inputData['name'], ':desc' => $inputData['description'] ?? '', ':price' => floatval($inputData['base_price']), ':cat_id' => !empty($inputData['category_id']) ? intval($inputData['category_id']) : null, ':chart_id' => !empty($inputData['size_chart_id']) ? intval($inputData['size_chart_id']) : null, ':seller_id' => $_SESSION['user_id'] ?? null ]); $productId = $conn->lastInsertId(); // 5.2 ดึงหรือบันทึกคุณลักษณะ สี/ไซซ์ ลงฐานข้อมูล เพื่อเอา ID ค่าเหล่านั้น $colorValIds = []; $sizeValIds = []; // ตรวจสอบแอตทริบิวต์สี if (!empty($inputData['colors'])) { foreach ($inputData['colors'] as $color) { $colorName = trim($color['name']); $colorHex = trim($color['code'] ?? '#000000'); $stmtGetVal = $conn->prepare("SELECT id FROM attribute_values WHERE attribute_id = 1 AND value = :val"); $stmtGetVal->execute([':val' => $colorName]); $valId = $stmtGetVal->fetchColumn(); if (!$valId) { $stmtInsVal = $conn->prepare("INSERT INTO attribute_values (attribute_id, value, color_code) VALUES (1, :val, :code)"); $stmtInsVal->execute([':val' => $colorName, ':code' => $colorHex]); $valId = $conn->lastInsertId(); } $colorValIds[$colorName] = $valId; } } // ตรวจสอบแอตทริบิวต์ไซซ์ if (!empty($inputData['sizes'])) { foreach ($inputData['sizes'] as $sizeName) { $sizeName = trim($sizeName); $stmtGetVal = $conn->prepare("SELECT id FROM attribute_values WHERE attribute_id = 2 AND value = :val"); $stmtGetVal->execute([':val' => $sizeName]); $valId = $stmtGetVal->fetchColumn(); if (!$valId) { $stmtInsVal = $conn->prepare("INSERT INTO attribute_values (attribute_id, value) VALUES (2, :val)"); $stmtInsVal->execute([':val' => $sizeName]); $valId = $conn->lastInsertId(); } $sizeValIds[$sizeName] = $valId; } } // 5.3 บันทึกรูปภาพสินค้า พร้อมผูกกับไอดีแอตทริบิวต์สี (จำลอง URL รูปภาพ) if (!empty($inputData['images'])) { foreach ($inputData['images'] as $index => $img) { $colorName = $img['color_name'] ?? null; $colorValId = ($colorName && isset($colorValIds[$colorName])) ? $colorValIds[$colorName] : null; $stmtImg = $conn->prepare(" INSERT INTO product_images (product_id, image_url, color_attribute_value_id, is_main, sort_order) VALUES (:prod_id, :url, :color_val_id, :is_main, :sort) "); $stmtImg->execute([ ':prod_id' => $productId, ':url' => $img['url'], ':color_val_id' => $colorValId, ':is_main' => ($index === 0) ? 1 : 0, ':sort' => $index ]); } } // 5.4 บันทึกรายการ Variants Matrix (ถ้าผู้ขายไม่ได้กำหนดไว้ ให้สร้าง Default Variant ให้อัตโนมัติ) if (!empty($inputData['variants'])) { foreach ($inputData['variants'] as $variant) { $stmtVar = $conn->prepare(" INSERT INTO product_variants (product_id, sku, price_modifier, stock_quantity) VALUES (:prod_id, :sku, :price_mod, :stock) "); $stmtVar->execute([ ':prod_id' => $productId, ':sku' => $variant['sku'], ':price_mod' => floatval($variant['price_modifier'] ?? 0), ':stock' => intval($variant['stock_quantity'] ?? 0) ]); $variantId = $conn->lastInsertId(); // เชื่อมสัมพันธ์ Option values (สี และ ไซซ์) ของ Variant นี้ $cName = $variant['color_name']; $sName = $variant['size_name']; if (isset($colorValIds[$cName])) { $stmtMap = $conn->prepare("INSERT INTO variant_option_values (variant_id, attribute_value_id) VALUES (:v_id, :val_id)"); $stmtMap->execute([':v_id' => $variantId, ':val_id' => $colorValIds[$cName]]); } if (isset($sizeValIds[$sName])) { $stmtMap = $conn->prepare("INSERT INTO variant_option_values (variant_id, attribute_value_id) VALUES (:v_id, :val_id)"); $stmtMap->execute([':v_id' => $variantId, ':val_id' => $sizeValIds[$sName]]); } } } else { // สร้าง Default Variant สำหรับสินค้าทั่วไป $stmtDefVar = $conn->prepare(" INSERT INTO product_variants (product_id, sku, price_modifier, stock_quantity) VALUES (:prod_id, :sku, 0.00, 50) "); $stmtDefVar->execute([ ':prod_id' => $productId, ':sku' => 'SKU-PROD-' . $productId . '-DEF' ]); $defVariantId = $conn->lastInsertId(); // ผูกกับสีมาตรฐาน (id 15) และ Free Size (id 16) $stmtMapDef1 = $conn->prepare("INSERT IGNORE INTO variant_option_values (variant_id, attribute_value_id) VALUES (:v_id, 15)"); $stmtMapDef1->execute([':v_id' => $defVariantId]); $stmtMapDef2 = $conn->prepare("INSERT IGNORE INTO variant_option_values (variant_id, attribute_value_id) VALUES (:v_id, 16)"); $stmtMapDef2->execute([':v_id' => $defVariantId]); } $conn->commit(); echo json_encode(['success' => true, 'product_id' => $productId]); } catch (Exception $e) { $conn->rollBack(); echo json_encode(['success' => false, 'message' => $e->getMessage()]); } break; // 6. อัปโหลดรูปภาพ (บันทึกไฟล์ลงโฟลเดอร์ uploads/) case 'upload_image': if (!isSellerLoggedIn()) { echo json_encode(['success' => false, 'message' => 'ไม่มีสิทธิ์ในการอัปโหลดรูปภาพ (Unauthorized) กรุณาเข้าสู่ระบบ']); exit; } if (!isset($_FILES['image'])) { echo json_encode(['success' => false, 'message' => 'ไม่พบไฟล์รูปภาพ']); exit; } $file = $_FILES['image']; $ext = pathinfo($file['name'], PATHINFO_EXTENSION); $allowed = ['jpg', 'jpeg', 'png', 'webp', 'gif']; if (!in_array(strtolower($ext), $allowed)) { echo json_encode(['success' => false, 'message' => 'รองรับเฉพาะไฟล์รูปภาพเท่านั้น (jpg, png, webp, gif)']); exit; } // สร้างโฟลเดอร์ uploads หากไม่มีอยู่ $uploadDir = __DIR__ . '/uploads/'; if (!file_exists($uploadDir)) { mkdir($uploadDir, 0777, true); } $fileName = 'prod_' . uniqid() . '.' . $ext; $targetPath = $uploadDir . $fileName; if (move_uploaded_file($file['tmp_name'], $targetPath)) { // ส่ง URL ท้องถิ่นกลับไป $localUrl = 'uploads/' . $fileName; echo json_encode(['success' => true, 'url' => $localUrl]); } else { echo json_encode(['success' => false, 'message' => 'เกิดความผิดพลาดระหว่างบันทึกไฟล์']); } break; // 7. สลับสถานะกดถูกใจสินค้า (Toggle Like / Wishlist) case 'toggle_like': if (!isLoggedIn()) { echo json_encode(['success' => false, 'require_login' => true, 'message' => 'กรุณาเข้าสู่ระบบเพื่อใช้งานระบบกดถูกใจสินค้า']); exit; } $productId = intval($inputData['product_id'] ?? 0); if (!$productId) { echo json_encode(['success' => false, 'message' => 'รหัสสินค้าไม่ถูกต้อง']); exit; } $userId = $_SESSION['user_id']; try { // ตรวจสอบว่าเคย Like หรือยัง $stmt = $conn->prepare("SELECT id FROM product_likes WHERE user_id = :u_id AND product_id = :p_id"); $stmt->execute([':u_id' => $userId, ':p_id' => $productId]); $like = $stmt->fetch(); if ($like) { // เคย Like แล้ว -> ยกเลิก Like $del = $conn->prepare("DELETE FROM product_likes WHERE user_id = :u_id AND product_id = :p_id"); $del->execute([':u_id' => $userId, ':p_id' => $productId]); $liked = false; $message = 'ยกเลิกการถูกใจสินค้าแล้ว'; } else { // ยังไม่เคย Like -> เพิ่ม Like $ins = $conn->prepare("INSERT INTO product_likes (user_id, product_id) VALUES (:u_id, :p_id)"); $ins->execute([':u_id' => $userId, ':p_id' => $productId]); $liked = true; $message = 'เพิ่มสินค้าในรายการถูกใจเรียบร้อย'; } // นับจำนวน Like รวมของสินค้านี้ $countStmt = $conn->prepare("SELECT COUNT(*) FROM product_likes WHERE product_id = :p_id"); $countStmt->execute([':p_id' => $productId]); $likesCount = $countStmt->fetchColumn(); echo json_encode([ 'success' => true, 'liked' => $liked, 'likes_count' => $likesCount, 'message' => $message ]); } catch (PDOException $e) { echo json_encode(['success' => false, 'message' => $e->getMessage()]); } break; default: echo json_encode(['success' => false, 'message' => 'ไม่พบ Action ที่ร้องขอ']); break; } ?>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.31 |
proxy
|
phpinfo
|
Settings