PHP MVC模式下基于Session数组实现购物车的技术求助
Hey there! As a PHP dev who’s been through the "first MVC project" grind, let’s walk through exactly how to build this session-based shopping cart for your assignment. We’ll stick strictly to MVC, no database required, and nail that dropdown navigation too.
First, let’s organize your files properly—this is the core of MVC. Create these folders and files in your project root:
your-shop-cart/ ├── controllers/ │ ├── OrderController.php │ └── ProductController.php ├── views/ │ ├── header.php │ ├── footer.php │ ├── order_create.php │ ├── order_list.php │ └── product_list.php └── index.php (entry point & router)
index.php) This file handles routing, initializes the session, and loads the right controller/action. It’s the first thing the server hits.
<?php // Start session BEFORE any HTML output session_start(); // Initialize empty cart if it doesn't exist in session if (!isset($_SESSION['cart'])) { $_SESSION['cart'] = []; } // Basic routing logic (super simple for beginners) $controller = $_GET['controller'] ?? 'Product'; // Default to Product list $action = $_GET['action'] ?? 'list'; // Default to list action // Load the controller file $controllerPath = "controllers/{$controller}Controller.php"; if (file_exists($controllerPath)) { require_once $controllerPath; $controllerClass = "{$controller}Controller"; $controllerInstance = new $controllerClass(); // Run the requested action if (method_exists($controllerInstance, $action)) { $controllerInstance->$action(); } else { echo "Oops! Action {$action} doesn't exist."; } } else { echo "Oops! Controller {$controller} doesn't exist."; } ?>
This is where you’ll build the dropdown navigation bar. We’ll add some basic CSS to make it functional and clean:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My Shop Cart</title> <style> nav { background: #f8f9fa; padding: 1rem; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .dropdown { display: inline-block; position: relative; margin-right: 2rem; } .dropdown-btn { padding: 0.5rem 1rem; border: none; background: #007bff; color: white; border-radius: 4px; cursor: pointer; } .dropdown-menu { display: none; position: absolute; top: 100%; left: 0; background: white; box-shadow: 0 4px 8px rgba(0,0,0,0.1); border-radius: 4px; padding: 0; margin: 0.5rem 0 0 0; list-style: none; } .dropdown-menu li a { display: block; padding: 0.75rem 1.5rem; text-decoration: none; color: #333; } .dropdown-menu li a:hover { background: #f8f9fa; } .dropdown:hover .dropdown-menu { display: block; } </style> </head> <body> <nav> <div class="dropdown"> <button class="dropdown-btn">Order</button> <ul class="dropdown-menu"> <li><a href="index.php?controller=Order&action=create">Create</a></li> <li><a href="index.php?controller=Order&action=list">List</a></li> </ul> </div> <div class="dropdown"> <button class="dropdown-btn">Product</button> <ul class="dropdown-menu"> <li><a href="index.php?controller=Product&action=list">Product List</a></li> </ul> </div> </nav> <main style="padding: 2rem;">
Don’t forget the footer.php to close the HTML:
</main> </body> </html>
controllers/OrderController.php) This handles all cart actions: showing the "add item" form, saving to session, and displaying the cart list.
<?php class OrderController { // Show the form to add items to cart public function create() { // Pre-fill form if coming from product list (optional but user-friendly) $productId = $_GET['product_id'] ?? ''; $productName = $_GET['product_name'] ?? ''; $price = $_GET['price'] ?? ''; require_once 'views/header.php'; require_once 'views/order_create.php'; require_once 'views/footer.php'; } // Save form data to session cart public function store() { if ($_SERVER['REQUEST_METHOD'] !== 'POST') { header('Location: index.php?controller=Order&action=create'); exit; } // Sanitize input (always do this to avoid XSS!) $productId = htmlspecialchars($_POST['product_id']); $productName = htmlspecialchars($_POST['product_name']); $price = floatval($_POST['price']); $quantity = intval($_POST['quantity']); // Calculate total for this item $total = $price * $quantity; // Check if item is already in cart—update quantity if yes $itemExists = false; foreach ($_SESSION['cart'] as &$item) { if ($item['product_id'] === $productId) { $item['quantity'] += $quantity; $item['total'] += $total; $itemExists = true; break; } } // Add new item if it doesn't exist if (!$itemExists) { $_SESSION['cart'][] = [ 'product_id' => $productId, 'product_name' => $productName, 'price' => $price, 'quantity' => $quantity, 'total' => $total ]; } // Redirect to cart list after saving header('Location: index.php?controller=Order&action=list'); exit; } // Display all items in cart public function list() { $cartItems = $_SESSION['cart']; // Calculate grand total $grandTotal = array_reduce($cartItems, function($sum, $item) { return $sum + $item['total']; }, 0); require_once 'views/header.php'; require_once 'views/order_list.php'; require_once 'views/footer.php'; } } ?>
views/order_create.php (Add Item Form)
<h1>Add Item to Cart</h1> <form method="POST" action="index.php?controller=Order&action=store"> <div style="margin-bottom: 1rem;"> <label>Product ID:</label> <input type="text" name="product_id" value="<?php echo $productId; ?>" required style="margin-left: 0.5rem;"> </div> <div style="margin-bottom: 1rem;"> <label>Product Name:</label> <input type="text" name="product_name" value="<?php echo $productName; ?>" required style="margin-left: 0.5rem;"> </div> <div style="margin-bottom: 1rem;"> <label>Price:</label> <input type="number" step="0.01" name="price" value="<?php echo $price; ?>" required style="margin-left: 0.5rem;"> </div> <div style="margin-bottom: 1rem;"> <label>Quantity:</label> <input type="number" min="1" name="quantity" value="1" required style="margin-left: 0.5rem;"> </div> <button type="submit" style="padding: 0.5rem 1rem; background: #28a745; color: white; border: none; border-radius: 4px;">Add to Cart</button> </form>
views/order_list.php (Cart List)
<h1>Your Shopping Cart</h1> <?php if (empty($cartItems)): ?> <p>Your cart is empty—start adding items!</p> <?php else: ?> <table style="border-collapse: collapse; width: 100%; margin-top: 1rem;"> <thead> <tr style="background: #f8f9fa;"> <th style="border: 1px solid #ddd; padding: 0.75rem;">Product ID</th> <th style="border: 1px solid #ddd; padding: 0.75rem;">Product Name</th> <th style="border: 1px solid #ddd; padding: 0.75rem;">Price</th> <th style="border: 1px solid #ddd; padding: 0.75rem;">Quantity</th> <th style="border: 1px solid #ddd; padding: 0.75rem;">Total</th> </tr> </thead> <tbody> <?php foreach ($cartItems as $item): ?> <tr> <td style="border: 1px solid #ddd; padding: 0.75rem;"><?php echo $item['product_id']; ?></td> <td style="border: 1px solid #ddd; padding: 0.75rem;"><?php echo $item['product_name']; ?></td> <td style="border: 1px solid #ddd; padding: 0.75rem;">$<?php echo number_format($item['price'], 2); ?></td> <td style="border: 1px solid #ddd; padding: 0.75rem;"><?php echo $item['quantity']; ?></td> <td style="border: 1px solid #ddd; padding: 0.75rem;">$<?php echo number_format($item['total'], 2); ?></td> </tr> <?php endforeach; ?> <tr style="font-weight: bold;"> <td colspan="4" style="border: 1px solid #ddd; padding: 0.75rem; text-align: right;">Grand Total:</td> <td style="border: 1px solid #ddd; padding: 0.75rem;">$<?php echo number_format($grandTotal, 2); ?></td> </tr> </tbody> </table> <?php endif; ?>
This is a simple product list to let users quickly add items (instead of typing everything manually):
controllers/ProductController.php
<?php class ProductController { // Show mock product list (no database needed!) public function list() { $products = [ ['id' => 'P001', 'name' => 'Wireless Headphones', 'price' => 149.99], ['id' => 'P002', 'name' => 'Mechanical Keyboard', 'price' => 89.99], ['id' => 'P003', 'name' => 'USB-C Charger', 'price' => 29.99] ]; require_once 'views/header.php'; require_once 'views/product_list.php'; require_once 'views/footer.php'; } } ?>
views/product_list.php
<h1>Our Products</h1> <div style="display: flex; gap: 2rem; margin-top: 2rem;"> <?php foreach ($products as $product): ?> <div style="border: 1px solid #ddd; border-radius: 4px; padding: 1.5rem; width: 200px;"> <h3><?php echo $product['name']; ?></h3> <p>Price: $<?php echo number_format($product['price'], 2); ?></p> <a href="index.php?controller=Order&action=create&product_id=<?php echo $product['id']; ?>&product_name=<?php echo urlencode($product['name']); ?>&price=<?php echo $product['price']; ?>" style="display: inline-block; margin-top: 1rem; padding: 0.5rem 1rem; background: #007bff; color: white; text-decoration: none; border-radius: 4px;">Add to Cart</a> </div> <?php endforeach; ?> </div>
- Always sanitize input: Use
htmlspecialchars()and type casting to prevent XSS attacks. - Session persistence: The cart will stay until the user closes their browser or you clear the session (add a "Clear Cart" button if you want!).
- Test step by step: First test the navigation, then the form submission, then the cart display—don’t try to run everything at once.
内容的提问来源于stack exchange,提问作者aita.kane

