File manager - Edit - /home/webapp69.cm.in.th/u69319090024/Shop24/product_edit.php
Back
<?php require_once __DIR__ . '/header.php'; if (!is_admin()) { header('Location: index.php'); exit; } $product_id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT) ?: filter_input(INPUT_POST, 'product_id', FILTER_VALIDATE_INT); $message = ''; $message_type = ''; // ── ฟังก์ชันช่วย upload รูปภาพ ────────────────────────────────── function upload_product_image(string $file_key): ?string { if (!isset($_FILES[$file_key]) || $_FILES[$file_key]['error'] !== UPLOAD_ERR_OK) { return null; } $ext = strtolower(pathinfo($_FILES[$file_key]['name'], PATHINFO_EXTENSION)); $allowed = ['jpg', 'jpeg', 'png', 'gif', 'webp']; if (!in_array($ext, $allowed)) return null; $filename = 'prod_' . time() . '_' . uniqid() . '.' . $ext; $target_dir = __DIR__ . '/assets/images/'; if (!is_dir($target_dir)) mkdir($target_dir, 0777, true); if (move_uploaded_file($_FILES[$file_key]['tmp_name'], $target_dir . $filename)) { return $filename; } return null; } // ── บันทึกการแก้ไขสินค้า ───────────────────────────────────────── if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'save_edit') { $id = filter_input(INPUT_POST, 'product_id', FILTER_VALIDATE_INT); $name = trim($_POST['name'] ?? ''); $description = trim($_POST['description'] ?? ''); $price = filter_input(INPUT_POST, 'price', FILTER_VALIDATE_FLOAT); $stock = filter_input(INPUT_POST, 'stock', FILTER_VALIDATE_INT); $sizes_raw = trim($_POST['sizes'] ?? ''); // ── จัดการรูปภาพ ────────────────────────────────────── // รูปหน้า (image) $image_front_new = upload_product_image('image_front_file'); $image_front = $image_front_new ?: trim($_POST['image_front_name'] ?? ''); // รูปหลัง $image_back_new = upload_product_image('image_back_file'); $image_back = $image_back_new ?: trim($_POST['image_back_name'] ?? ''); // สร้าง array ไซส์ ลบช่องว่าง $sizes_arr = array_filter(array_map('trim', explode(',', $sizes_raw))); $sizes_json = !empty($sizes_arr) ? json_encode(array_values($sizes_arr), JSON_UNESCAPED_UNICODE) : null; if ($id && $name && $price !== false && $stock !== false) { // รูปหลักใน column image ใช้รูปหน้า $stmt = $pdo->prepare(" UPDATE products SET name = ?, description = ?, price = ?, stock = ?, image = ?, image_back = ?, sizes = ? WHERE id = ? "); $main_img = $image_front ?: 'default.jpg'; $stmt->execute([$name, $description, $price, $stock, $main_img, ($image_back ?: null), $sizes_json, $id]); $message = 'บันทึกข้อมูลสินค้าเรียบร้อยแล้ว!'; $message_type = 'success'; $product_id = $id; } else { $message = 'กรุณากรอกข้อมูลสินค้าให้ครบถ้วน'; $message_type = 'danger'; } } // ── จัดการข้อมูลสีและรูปภาพ (Variants) ─────────────────────────── if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { if ($_POST['action'] === 'add_variant') { $id = filter_input(INPUT_POST, 'product_id', FILTER_VALIDATE_INT); $color_name = trim($_POST['color_name'] ?? ''); $v_front = upload_product_image('variant_front_file'); $v_back = upload_product_image('variant_back_file'); if ($id && $color_name) { $stmt = $pdo->prepare("INSERT INTO product_variants (product_id, color_name, image_front, image_back) VALUES (?, ?, ?, ?)"); $stmt->execute([$id, $color_name, $v_front, $v_back]); $message = "เพิ่มเฉดสี <strong>" . htmlspecialchars($color_name) . "</strong> เรียบร้อยแล้ว!"; $message_type = "success"; $product_id = $id; } else { $message = "กรุณากรอกชื่อสีให้เรียบร้อย"; $message_type = "danger"; } } if ($_POST['action'] === 'delete_variant') { $id = filter_input(INPUT_POST, 'product_id', FILTER_VALIDATE_INT); $variant_id = filter_input(INPUT_POST, 'variant_id', FILTER_VALIDATE_INT); if ($id && $variant_id) { // ดึงชื่อไฟล์มาลบ $stmt_file = $pdo->prepare("SELECT image_front, image_back FROM product_variants WHERE id = ? AND product_id = ?"); $stmt_file->execute([$variant_id, $id]); $var_files = $stmt_file->fetch(); if ($var_files) { if (!empty($var_files['image_front']) && $var_files['image_front'] !== 'default.jpg') { @unlink(__DIR__ . '/assets/images/' . $var_files['image_front']); } if (!empty($var_files['image_back'])) { @unlink(__DIR__ . '/assets/images/' . $var_files['image_back']); } } $stmt = $pdo->prepare("DELETE FROM product_variants WHERE id = ? AND product_id = ?"); $stmt->execute([$variant_id, $id]); $message = "ลบตัวเลือกสีเรียบร้อยแล้ว"; $message_type = "info"; $product_id = $id; } } } // ── ดึงข้อมูลสินค้า ───────────────────────────────────────────── if (!$product_id) { header('Location: admin_products.php'); exit; } $stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?"); $stmt->execute([$product_id]); $p = $stmt->fetch(); if (!$p) { header('Location: admin_products.php'); exit; } $sizes_list = []; if (!empty($p['sizes'])) { $decoded = json_decode($p['sizes'], true); if (is_array($decoded)) $sizes_list = $decoded; } $stmt_var = $pdo->prepare("SELECT * FROM product_variants WHERE product_id = ? ORDER BY id ASC"); $stmt_var->execute([$p['id']]); $variants = $stmt_var->fetchAll(); $img_front = get_product_image_url($p['image']); $img_back = !empty($p['image_back']) ? get_product_image_url($p['image_back']) : null; ?> <!-- Page Header --> <div class="d-flex align-items-center gap-3 mb-4"> <a href="admin_products.php" class="btn btn-light rounded-pill px-3"> <i class="fa-solid fa-arrow-left me-1"></i> กลับ </a> <div> <h3 class="fw-bold mb-0"><i class="fa-solid fa-pen-to-square text-primary me-2"></i>แก้ไขสินค้า</h3> <small class="text-muted">รหัสสินค้า #<?= $p['id'] ?> — <?= htmlspecialchars($p['name']) ?></small> </div> </div> <?php if (!empty($message)): ?> <div class="alert alert-<?= $message_type ?> alert-dismissible fade show rounded-3" role="alert"> <i class="fa-solid fa-circle-<?= $message_type === 'success' ? 'check' : 'xmark' ?> me-2"></i> <?= $message ?> <button type="button" class="btn-close" data-bs-dismiss="alert"></button> </div> <?php endif; ?> <form method="POST" action="product_edit.php" enctype="multipart/form-data"> <input type="hidden" name="action" value="save_edit"> <input type="hidden" name="product_id" value="<?= $p['id'] ?>"> <div class="row g-4"> <!-- ─── คอลัมน์ซ้าย: รูปภาพ ─────────────────────── --> <div class="col-lg-5"> <!-- รูปหน้า --> <div class="card border-0 shadow-sm rounded-4 mb-4"> <div class="card-header bg-white border-bottom-0 pt-4 px-4 pb-0"> <h6 class="fw-bold mb-0"> <i class="fa-solid fa-image text-primary me-2"></i>รูปด้านหน้าสินค้า </h6> </div> <div class="card-body px-4 pb-4"> <div class="product-preview-box mb-3 rounded-4 overflow-hidden border d-flex align-items-center justify-content-center" style="height: 220px; background: #f8fafc;"> <img id="preview_front" src="<?= htmlspecialchars($img_front) ?>" style="max-height: 210px; max-width: 100%; object-fit: contain;" alt="รูปหน้า"> </div> <label class="form-label fw-medium text-muted small">อัปโหลดรูปใหม่</label> <input type="file" name="image_front_file" id="image_front_file" class="form-control mb-2" accept="image/*" onchange="previewImg(this,'preview_front')"> <input type="text" name="image_front_name" class="form-control form-control-sm" value="<?= htmlspecialchars($p['image'] ?? '') ?>" placeholder="หรือระบุชื่อไฟล์เดิม"> </div> </div> <!-- รูปหลัง --> <div class="card border-0 shadow-sm rounded-4"> <div class="card-header bg-white border-bottom-0 pt-4 px-4 pb-0"> <h6 class="fw-bold mb-0"> <i class="fa-solid fa-image text-secondary me-2"></i>รูปด้านหลังสินค้า </h6> </div> <div class="card-body px-4 pb-4"> <div class="product-preview-box mb-3 rounded-4 overflow-hidden border d-flex align-items-center justify-content-center" style="height: 220px; background: #f8fafc;"> <?php if ($img_back): ?> <img id="preview_back" src="<?= htmlspecialchars($img_back) ?>" style="max-height: 210px; max-width: 100%; object-fit: contain;" alt="รูปหลัง"> <?php else: ?> <div id="preview_back_placeholder" class="text-center text-muted"> <i class="fa-solid fa-image fa-3x mb-2 opacity-25"></i> <div class="small">ยังไม่มีรูปด้านหลัง</div> </div> <img id="preview_back" src="" style="max-height: 210px; max-width: 100%; object-fit: contain; display:none;" alt="รูปหลัง"> <?php endif; ?> </div> <label class="form-label fw-medium text-muted small">อัปโหลดรูปหลังใหม่</label> <input type="file" name="image_back_file" id="image_back_file" class="form-control mb-2" accept="image/*" onchange="previewImg(this,'preview_back')"> <input type="text" name="image_back_name" class="form-control form-control-sm" value="<?= htmlspecialchars($p['image_back'] ?? '') ?>" placeholder="หรือระบุชื่อไฟล์เดิม"> </div> </div> </div> <!-- ─── คอลัมน์ขวา: ข้อมูลสินค้า ───────────────── --> <div class="col-lg-7"> <div class="card border-0 shadow-sm rounded-4 h-100"> <div class="card-header bg-white border-bottom-0 pt-4 px-4 pb-0"> <h6 class="fw-bold mb-0"> <i class="fa-solid fa-clipboard-list text-primary me-2"></i>รายละเอียดสินค้า </h6> </div> <div class="card-body px-4 pb-4"> <!-- ชื่อสินค้า --> <div class="mb-3"> <label class="form-label fw-semibold">ชื่อสินค้า <span class="text-danger">*</span></label> <input type="text" name="name" class="form-control" value="<?= htmlspecialchars($p['name']) ?>" required> </div> <!-- รายละเอียด --> <div class="mb-3"> <label class="form-label fw-semibold">รายละเอียดสินค้า</label> <textarea name="description" class="form-control" rows="4" placeholder="อธิบายคุณสมบัติ วัสดุ ความพิเศษของสินค้า..." ><?= htmlspecialchars($p['description'] ?? '') ?></textarea> </div> <!-- ราคา + สต็อก --> <div class="row g-3 mb-3"> <div class="col-sm-6"> <label class="form-label fw-semibold">ราคาขาย (บาท) <span class="text-danger">*</span></label> <div class="input-group"> <span class="input-group-text">฿</span> <input type="number" name="price" class="form-control" value="<?= $p['price'] ?>" step="0.01" min="0" required> </div> </div> <div class="col-sm-6"> <label class="form-label fw-semibold">จำนวนสต็อก (ชิ้น) <span class="text-danger">*</span></label> <div class="input-group"> <input type="number" name="stock" class="form-control" value="<?= $p['stock'] ?>" min="0" required> <span class="input-group-text">ชิ้น</span> </div> </div> </div> <!-- ── ไซส์สินค้า ── --> <div class="mb-4"> <label class="form-label fw-semibold"> <i class="fa-solid fa-ruler-combined text-primary me-1"></i>ขนาด / ไซส์สินค้า </label> <div class="d-flex flex-wrap gap-2 mb-2" id="sizes_tags_container"> <?php foreach ($sizes_list as $sz): ?> <span class="badge rounded-pill size-badge d-flex align-items-center gap-1" style="background:#e8efff; color:#3b5bdb; font-size:.88rem; padding:.4em .85em;"> <?= htmlspecialchars($sz) ?> <i class="fa-solid fa-xmark ms-1 size-remove" style="cursor:pointer;"></i> </span> <?php endforeach; ?> </div> <div class="input-group"> <input type="text" id="size_input" class="form-control" placeholder="เช่น S, M, L, XL, 38, 40 แล้วกด Enter หรือ +"> <button type="button" class="btn btn-outline-primary" onclick="addSize()"> <i class="fa-solid fa-plus"></i> </button> </div> <input type="hidden" name="sizes" id="sizes_hidden" value="<?= htmlspecialchars(implode(', ', $sizes_list)) ?>"> <small class="text-muted">พิมพ์ไซส์แล้วกด Enter หรือกดปุ่ม + เพื่อเพิ่ม, กด × เพื่อลบ</small> </div> <!-- ปุ่มบันทึก --> <div class="d-flex gap-2 pt-2"> <button type="submit" class="btn btn-primary-custom rounded-pill px-5 fw-semibold"> <i class="fa-solid fa-floppy-disk me-2"></i>บันทึกการแก้ไข </button> <a href="admin_products.php" class="btn btn-light rounded-pill px-4">ยกเลิก</a> </div> </div> </div> </div> </div><!-- /row --> </form> <!-- ─── ส่วนจัดการเฉดสีเพิ่มเติม ────────────────────────── --> <div class="card border-0 shadow-sm rounded-4 mt-4 mb-4"> <div class="card-header bg-white border-bottom-0 pt-4 px-4 pb-0"> <h5 class="fw-bold mb-1"> <i class="fa-solid fa-palette text-danger me-2"></i>ตัวเลือกสี & รูปภาพเพิ่มเติม (สำหรับเสื้อหลากสี) </h5> <p class="text-muted small mb-0">สามารถเพิ่มเฉดสีต่างๆ ของสินค้าชิ้นนี้ โดย 1 สีจะระบุรูปหน้าและรูปหลังแยกกันได้</p> </div> <div class="card-body p-4"> <!-- รายการสีที่มีอยู่แล้ว --> <h6 class="fw-bold mb-3 text-dark">เฉดสีที่เปิดใช้งานอยู่ (<?= count($variants) ?> สี)</h6> <?php if (empty($variants)): ?> <div class="alert alert-light border text-center py-4 rounded-3 text-muted mb-4"> <i class="fa-solid fa-palette fa-2x mb-2 opacity-50"></i> <div>ยังไม่มีการเพิ่มสีเพิ่มเติม (แสดงเฉพาะภาพหลักสินค้า)</div> </div> <?php else: ?> <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-3 mb-4"> <?php foreach ($variants as $var): ?> <div class="col"> <div class="card border rounded-4 overflow-hidden h-100 shadow-sm"> <div class="card-body p-3"> <div class="d-flex justify-content-between align-items-center mb-2"> <span class="badge bg-primary rounded-pill px-3 py-2 fw-semibold"> <i class="fa-solid fa-paint-brush me-1"></i><?= htmlspecialchars($var['color_name']) ?> </span> <form method="POST" action="product_edit.php" onsubmit="return confirm('ต้องการลบสีนี้หรือไม่?');"> <input type="hidden" name="action" value="delete_variant"> <input type="hidden" name="product_id" value="<?= $p['id'] ?>"> <input type="hidden" name="variant_id" value="<?= $var['id'] ?>"> <button type="submit" class="btn btn-sm btn-link text-danger p-0 border-0 bg-transparent" title="ลบสีนี้"> <i class="fa-solid fa-trash-can"></i> ลบสีนี้ </button> </form> </div> <div class="row g-2 text-center"> <div class="col-6"> <div class="p-2 border rounded-3 bg-light" style="height: 110px; display: flex; align-items: center; justify-content: center;"> <?php if ($var['image_front']): ?> <img src="<?= htmlspecialchars(get_product_image_url($var['image_front'])) ?>" style="max-height: 90px; max-width: 100%; object-fit: contain;"> <?php else: ?> <small class="text-muted">ไม่มีรูปหน้า</small> <?php endif; ?> </div> <small class="text-muted mt-1 d-block small" style="font-size: 0.75rem;">ด้านหน้า</small> </div> <div class="col-6"> <div class="p-2 border rounded-3 bg-light" style="height: 110px; display: flex; align-items: center; justify-content: center;"> <?php if ($var['image_back']): ?> <img src="<?= htmlspecialchars(get_product_image_url($var['image_back'])) ?>" style="max-height: 90px; max-width: 100%; object-fit: contain;"> <?php else: ?> <small class="text-muted">ไม่มีรูปหลัง</small> <?php endif; ?> </div> <small class="text-muted mt-1 d-block small" style="font-size: 0.75rem;">ด้านหลัง</small> </div> </div> </div> </div> </div> <?php endforeach; ?> </div> <?php endif; ?> <hr class="my-4"> <!-- ฟอร์มเพิ่มสีใหม่ --> <h6 class="fw-bold mb-3 text-dark"><i class="fa-solid fa-plus-circle text-success me-1"></i>เพิ่มเฉดสีและอัปโหลดรูปภาพใหม่</h6> <form method="POST" action="product_edit.php" enctype="multipart/form-data" class="bg-light p-3 rounded-4 border"> <input type="hidden" name="action" value="add_variant"> <input type="hidden" name="product_id" value="<?= $p['id'] ?>"> <div class="row g-3"> <div class="col-md-4"> <label class="form-label fw-semibold">ชื่อสี / เฉดสี</label> <input type="text" name="color_name" class="form-control" placeholder="เช่น สีแดงส้ม, สีขาวมุก, ลายกราฟิก" required> </div> <div class="col-md-4"> <label class="form-label fw-semibold">รูปภาพด้านหน้า</label> <input type="file" name="variant_front_file" class="form-control" accept="image/*" required> </div> <div class="col-md-4"> <label class="form-label fw-semibold">รูปภาพด้านหลัง (ถ้ามี)</label> <input type="file" name="variant_back_file" class="form-control" accept="image/*"> </div> </div> <div class="mt-3"> <button type="submit" class="btn btn-success rounded-pill px-4"> <i class="fa-solid fa-plus me-1"></i> เพิ่มเฉดสีนี้เข้ารายการ </button> </div> </form> </div> </div> <script> // ── Preview รูปภาพก่อน upload ───────────────────────────────── function previewImg(input, imgId) { const file = input.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = e => { const img = document.getElementById(imgId); img.src = e.target.result; img.style.display = ''; // ซ่อน placeholder ถ้ามี const ph = document.getElementById(imgId + '_placeholder'); if (ph) ph.style.display = 'none'; }; reader.readAsDataURL(file); } // ── ระบบ Tags ไซส์ ─────────────────────────────────────────── function updateSizesHidden() { const tags = [...document.querySelectorAll('#sizes_tags_container .size-badge')] .map(b => b.textContent.trim().replace(/×$/, '').trim()) .filter(s => s.length > 0); document.getElementById('sizes_hidden').value = tags.join(', '); } function addSize() { const input = document.getElementById('size_input'); const val = input.value.trim(); if (!val) return; // กรณีผู้ใช้พิมพ์หลายไซส์ด้วย comma หรือ space const parts = val.split(/[,\s]+/).filter(s => s.length > 0); parts.forEach(sz => { const badge = document.createElement('span'); badge.className = 'badge rounded-pill size-badge d-flex align-items-center gap-1'; badge.style.cssText = 'background:#e8efff; color:#3b5bdb; font-size:.88rem; padding:.4em .85em;'; badge.innerHTML = `${sz} <i class="fa-solid fa-xmark ms-1 size-remove" style="cursor:pointer;"></i>`; badge.querySelector('.size-remove').addEventListener('click', () => { badge.remove(); updateSizesHidden(); }); document.getElementById('sizes_tags_container').appendChild(badge); }); input.value = ''; updateSizesHidden(); } // Enter key ใน input document.getElementById('size_input').addEventListener('keydown', e => { if (e.key === 'Enter') { e.preventDefault(); addSize(); } }); // Remove listener สำหรับ badges ที่มีอยู่แล้ว document.querySelectorAll('.size-remove').forEach(btn => { btn.addEventListener('click', () => { btn.closest('.size-badge').remove(); updateSizesHidden(); }); }); </script> <?php require_once __DIR__ . '/footer.php'; ?>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.25 |
proxy
|
phpinfo
|
Settings