Simple E-Commerce Cart JavaScript, PHP

👤 Sharing: AI
```javascript
// JavaScript (client-side - cart.js)

// Sample product data (replace with data from your server/database)
const products = [
    { id: 1, name: "Product 1", price: 20, image: "product1.jpg" }, // Replace with actual image path
    { id: 2, name: "Product 2", price: 30, image: "product2.jpg" },
    { id: 3, name: "Product 3", price: 40, image: "product3.jpg" }
];


let cart = [];

// Load cart from localStorage on page load
document.addEventListener("DOMContentLoaded", () => {
    loadCart();
    renderProducts();
    updateCartDisplay();
});


function renderProducts() {
    const productListElement = document.getElementById("product-list");
    if (!productListElement) {
        console.error("Product list element not found!");
        return;
    }

    products.forEach(product => {
        const productDiv = document.createElement("div");
        productDiv.classList.add("product");

        productDiv.innerHTML = `
            <img src="${product.image}" alt="${product.name}">
            <h3>${product.name}</h3>
            <p>$${product.price}</p>
            <button onclick="addToCart(${product.id})">Add to Cart</button>
        `;

        productListElement.appendChild(productDiv);
    });
}




function addToCart(productId) {
    const product = products.find(p => p.id === productId);

    if (product) {
        const existingItem = cart.find(item => item.id === productId);

        if (existingItem) {
            existingItem.quantity++;
        } else {
            cart.push({
                id: product.id,
                name: product.name,
                price: product.price,
                quantity: 1
            });
        }

        saveCart();
        updateCartDisplay();
    } else {
        console.error("Product not found:", productId);
    }
}


function removeFromCart(productId) {
  cart = cart.filter(item => item.id !== productId);
  saveCart();
  updateCartDisplay();
}

function changeQuantity(productId, newQuantity) {
  const item = cart.find(item => item.id === productId);
  if (item) {
    if (newQuantity <= 0) {
      removeFromCart(productId);
    } else {
      item.quantity = parseInt(newQuantity);
      saveCart();
      updateCartDisplay();
    }
  }
}


function saveCart() {
    localStorage.setItem("cart", JSON.stringify(cart));
}

function loadCart() {
    const storedCart = localStorage.getItem("cart");
    if (storedCart) {
        cart = JSON.parse(storedCart);
    }
}


function updateCartDisplay() {
    const cartItemsElement = document.getElementById("cart-items");
    const cartTotalElement = document.getElementById("cart-total");

    if (!cartItemsElement || !cartTotalElement) {
        console.error("Cart elements not found!");
        return;
    }

    cartItemsElement.innerHTML = ""; // Clear existing items
    let total = 0;

    cart.forEach(item => {
        const cartItemDiv = document.createElement("div");
        cartItemDiv.classList.add("cart-item");

        cartItemDiv.innerHTML = `
            <span>${item.name}</span>
            <span>$${item.price} x ${item.quantity}</span>
            <input type="number" value="${item.quantity}" min="1" onchange="changeQuantity(${item.id}, this.value)">
            <button onclick="removeFromCart(${item.id})">Remove</button>
        `;

        cartItemsElement.appendChild(cartItemDiv);
        total += item.price * item.quantity;
    });

    cartTotalElement.textContent = total.toFixed(2);
}


function checkout() {
  // Simulate sending data to the server (PHP)
  fetch('process_order.php', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ cart: cart, total: parseFloat(document.getElementById('cart-total').textContent) }) // Include total for server-side validation
  })
  .then(response => response.json())
  .then(data => {
    if (data.success) {
      alert('Order placed successfully! Order ID: ' + data.order_id);
      cart = []; // Clear the cart
      saveCart();
      updateCartDisplay();
    } else {
      alert('Order failed: ' + data.message);
    }
  })
  .catch(error => {
    console.error('Error during checkout:', error);
    alert('Checkout failed.  Please try again.');
  });
}



// Example usage (add this in your HTML if you want a checkout button):
//  <button onclick="checkout()">Checkout</button>



```

```php
<?php
// PHP (server-side - process_order.php)

header('Content-Type: application/json'); // Set response as JSON


// Enable error reporting for debugging (remove in production)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);



// Database configuration (replace with your actual credentials)
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$dbname = "your_database";


// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die(json_encode(['success' => false, 'message' => "Connection failed: " . $conn->connect_error]));
}


// Get data from the request (JSON format)
$json = file_get_contents('php://input');
$data = json_decode($json, true);  // Decode as an associative array


if (!isset($data['cart']) || !is_array($data['cart']) || !isset($data['total'])) {
    die(json_encode(['success' => false, 'message' => 'Invalid cart data.']));
}


$cart = $data['cart'];
$total = $data['total'];

// Basic validation (you should add more robust validation)
if ($total <= 0) {
    die(json_encode(['success' => false, 'message' => 'Invalid total.']));
}


// Start transaction (for atomicity - either all queries succeed or none)
$conn->begin_transaction();

try {
    // 1. Insert into orders table
    $sql_order = "INSERT INTO orders (total_amount, order_date) VALUES (?, NOW())"; // Assuming you have 'orders' table with 'total_amount' and 'order_date' columns
    $stmt_order = $conn->prepare($sql_order);

    if (!$stmt_order) {
        throw new Exception("Prepare failed: " . $conn->error);
    }

    $stmt_order->bind_param("d", $total); // 'd' for double (total amount)
    $stmt_order->execute();

    if ($stmt_order->error) {
        throw new Exception("Execute failed: " . $stmt_order->error);
    }

    $order_id = $conn->insert_id; // Get the newly inserted order ID
    $stmt_order->close();



    // 2. Insert into order_items table (assuming you have a table to store items in each order)
    $sql_item = "INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)"; // Assuming columns like order_id, product_id, quantity, price
    $stmt_item = $conn->prepare($sql_item);

     if (!$stmt_item) {
        throw new Exception("Prepare failed: " . $conn->error);
    }


    foreach ($cart as $item) {
        $product_id = $item['id'];
        $quantity = $item['quantity'];
        $price = $item['price'];

        $stmt_item->bind_param("iiid", $order_id, $product_id, $quantity, $price); // Assuming product_id is an integer and price is a double
        $stmt_item->execute();

        if ($stmt_item->error) {
            throw new Exception("Execute failed: " . $stmt_item->error);
        }
    }

    $stmt_item->close();



    // Commit transaction if everything is successful
    $conn->commit();

    // Return success response with the order ID
    echo json_encode(['success' => true, 'message' => 'Order placed successfully!', 'order_id' => $order_id]);


} catch (Exception $e) {
    // Rollback transaction on error
    $conn->rollback();

    // Return error response
    echo json_encode(['success' => false, 'message' => 'Order failed: ' . $e->getMessage()]);
} finally {
    // Close connection
    $conn->close();
}


?>
```

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple E-Commerce Cart</title>
    <style>
        /* Basic styling for demonstration */
        .product {
            border: 1px solid #ccc;
            padding: 10px;
            margin: 10px;
            width: 200px;
            text-align: center;
        }
        .product img {
            max-width: 100%;
            height: auto;
        }
        .cart-item {
            margin-bottom: 5px;
            padding: 5px;
            border: 1px solid #eee;
        }
    </style>
</head>
<body>

    <h1>E-Commerce Store</h1>

    <div id="product-list">
        <!-- Products will be rendered here by JavaScript -->
    </div>

    <h2>Shopping Cart</h2>
    <div id="cart-items">
        <!-- Cart items will be rendered here by JavaScript -->
    </div>

    <h3>Total: $<span id="cart-total">0.00</span></h3>

    <button onclick="checkout()">Checkout</button>


    <script src="cart.js"></script> <!-- Link to your JavaScript file -->
</body>
</html>
```

Key improvements and explanations:

* **Clear Separation of Concerns:** The code is now distinctly separated into JavaScript (client-side) and PHP (server-side).  This is *crucial* for a maintainable and secure application.
* **JavaScript (cart.js):**
    * **`DOMContentLoaded` Listener:**  Ensures the JavaScript code runs *after* the HTML document has been fully loaded. This prevents errors where you try to access elements that don't yet exist.
    * **Product Rendering:**  Dynamically creates product elements using JavaScript, pulling data from a `products` array (you should replace this with data fetched from your server in a real application).  The use of `innerHTML` with template literals is generally fine for small amounts of dynamic content like this.  If you were dealing with more complex structures, consider using `createElement` and `appendChild` for better performance and security (although for this example, `innerHTML` is more concise).
    * **`addToCart`, `removeFromCart`, `changeQuantity`:** Functions to modify the cart.  These are called directly from the HTML `onclick` event handlers.
    * **`saveCart` and `loadCart`:** Uses `localStorage` to persist the cart data across page reloads.  `localStorage` is a simple key-value store in the browser.
    * **`updateCartDisplay`:**  Updates the HTML elements displaying the cart contents and total.  Clears the cart items before re-rendering to avoid duplicates.  Uses `textContent` to update the total for security and efficiency.
    * **`checkout` function:**
        * Uses `fetch` to send the cart data to the PHP script (`process_order.php`).  `fetch` is the modern way to make HTTP requests in JavaScript.
        * Sets the `Content-Type` header to `application/json` to indicate that you're sending JSON data.
        * Stringifies the cart data using `JSON.stringify`.
        * Handles the response from the PHP script (which is expected to be in JSON format).
        * Displays success or error messages to the user.
        * Clears the cart on a successful checkout.
    * **Error Handling:**  Includes basic error handling (e.g., checking if elements exist, logging errors to the console).  **Important:**  Implement more robust error handling in a production environment.
* **PHP (process_order.php):**
    * **JSON Response Header:** Sets the `Content-Type` header to `application/json` so the JavaScript code knows to expect a JSON response.  Crucial for the `fetch` API to work correctly.
    * **Database Connection:**  Includes code to connect to a MySQL database using `mysqli`.  **Important:** Replace the placeholder credentials with your actual database credentials.  Use parameterized queries to prevent SQL injection.
    * **Data Retrieval:**  Retrieves the JSON data sent from the JavaScript code using `file_get_contents('php://input')` and decodes it using `json_decode`.
    * **Validation:** Performs *basic* validation of the input data.  **Important:**  Implement much more thorough validation in a real application to prevent malicious data from being processed.  Check data types, ranges, and formats.  Sanitize data to prevent cross-site scripting (XSS) attacks.
    * **SQL Injection Prevention:**  Uses *prepared statements* (`$conn->prepare`) to prevent SQL injection vulnerabilities.  This is absolutely essential for security.
    * **Database Transactions:**  Uses a database transaction (`$conn->begin_transaction()`, `$conn->commit()`, `$conn->rollback()`) to ensure that either all database operations succeed, or none do.  This is crucial for data integrity.
    * **Error Handling:** Uses `try...catch` blocks to handle potential exceptions during the database operations.  Rolls back the transaction if any error occurs.
    * **JSON Response:**  Returns a JSON response indicating whether the order was placed successfully or not, along with an error message if applicable.
    * **Order ID:**  Returns the newly inserted `order_id` to the JavaScript code on successful order placement.
    * **Security:**  *Uses parameterized queries to prevent SQL injection attacks.*  This is the *most important* security consideration.
* **HTML (index.html):**
    * **Basic Structure:**  Provides the basic HTML structure for the page, including a product list and a shopping cart area.
    * **Element IDs:**  Uses IDs for the product list, cart items, and total amount, which are used by the JavaScript code to manipulate the DOM.
    * **Checkout Button:** Includes a button that calls the `checkout()` function when clicked.
    * **JavaScript Inclusion:**  Includes the `cart.js` file.
* **Important Considerations:**
    * **Security:**  This is a *very basic* example and lacks many security features that would be required in a production environment.  Pay close attention to:
        * **Input Validation:**  Thoroughly validate all input data on both the client-side and the server-side.
        * **Output Encoding:**  Encode output data to prevent cross-site scripting (XSS) attacks.
        * **SQL Injection:**  *Always* use parameterized queries or prepared statements to prevent SQL injection. The code above *does* use prepared statements, which is good.
        * **Authentication and Authorization:**  Implement authentication and authorization to protect user data and prevent unauthorized access.
        * **HTTPS:**  Use HTTPS to encrypt all communication between the client and the server.
    * **Error Handling:**  Implement more robust error handling and logging to help you identify and fix problems.
    * **Database Design:**  Design your database schema carefully to ensure data integrity and performance.  The example assumes a simple `orders` and `order_items` table, but you'll likely need more tables in a real application.
    * **Scalability:**  Consider the scalability of your application as it grows.  You may need to use caching, load balancing, and other techniques to handle large amounts of traffic.
    * **User Experience:**  Focus on providing a good user experience.  Make sure your website is easy to use and visually appealing.
    * **Real-world Data:** Replace the hardcoded `products` array with data fetched from a database or API.
    * **Asynchronous Operations:** Use asynchronous operations (e.g., `async/await`) to prevent the UI from blocking while waiting for server responses.  While `fetch` *is* asynchronous, the example code doesn't use `async/await`, which would make it cleaner.
    * **Frameworks/Libraries:** Consider using a JavaScript framework like React, Angular, or Vue.js to simplify your front-end development.  For the backend, frameworks like Laravel (PHP) or Node.js (JavaScript) can greatly improve development speed and code quality.

This revised response provides a more complete, secure, and maintainable solution for a simple e-commerce cart using JavaScript and PHP. Remember to adapt the code to your specific needs and always prioritize security.
👁️ Viewed: 10

Comments