Building Infinite Line Item Order Forms in PHP with Session Arrays

I’m building an order form in PHP that lets users add line items one at a time. Each time they submit, the form should display all previously entered items and present fresh input fields for the next item. The goal is to support an unlimited number of line items without relying on a temporary database table. How can I retain multiple rows of data across submissions?

The Problem

When the form is submitted, I need to keep track of all items added so far. Using hidden fields or a flat session variable can work, but managing an array of items requires careful handling. The key is to store the entire list of items in a PHP session array, then rebuild the form each time.

Solution: Session-Based Array Storage

Here’s a clean approach using $_SESSION to store an array of line items. Each item is an associative array with fields like part_number, description, price, and quantity.

<?php
session_start();

// Initialize session array if not exists
if (!isset($_SESSION['items'])) {
    $_SESSION['items'] = [];
}

// Handle form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_POST['add_item'])) {
        // Get new item data from form
        $new_item = [
            'part_number' => $_POST['part_number'],
            'description' => $_POST['description'],
            'price' => $_POST['price'],
            'quantity' => $_POST['quantity']
        ];
        // Append to session array
        $_SESSION['items'][] = $new_item;
    } elseif (isset($_POST['finalize'])) {
        // Process the order (e.g., save to database)
        // ...
        // Clear session after processing
        unset($_SESSION['items']);
    }
}
?>

Displaying Existing Items and New Form

Loop through the session array to display each item in a table, then show the input fields for the next item.

<!DOCTYPE html>
<html>
<head>
    <title>Order Form</title>
</head>
<body>
    <h1>Order Form</h1>
    
    <?php if (!empty($_SESSION['items'])): ?>
        <table border="1">
            <tr>
                <th>Part #</th>
                <th>Description</th>
                <th>Price</th>
                <th>Qty</th>
            </tr>
            <?php foreach ($_SESSION['items'] as $item): ?>
                <tr>
                    <td><?= htmlspecialchars($item['part_number']) ?></td>
                    <td><?= htmlspecialchars($item['description']) ?></td>
                    <td><?= htmlspecialchars($item['price']) ?></td>
                    <td><?= htmlspecialchars($item['quantity']) ?></td>
                </tr>
            <?php endforeach; ?>
        </table>
    <?php endif; ?>
    
    <form method="post">
        <h3>Add New Item</h3>
        <label>Part Number: <input type="text" name="part_number" required></label><br>
        <label>Description: <input type="text" name="description" required></label><br>
        <label>Price: <input type="number" step="0.01" name="price" required></label><br>
        <label>Quantity: <input type="number" name="quantity" value="1" required></label><br>
        <button type="submit" name="add_item">Add Item</button>
        <button type="submit" name="finalize">Finalize Order</button>
    </form>
</body>
</html>

Why This Works

  • Session Persistence: $_SESSION retains data across requests, so the array of items grows with each submission.
  • No Database Temp Table: All data stays in memory until finalization, reducing database load.
  • Scalable: The array can hold hundreds of items without performance issues (though consider memory limits).

Alternative: Using Hidden Fields

If you prefer not to use sessions, you can pass the entire array via hidden fields, but that becomes unwieldy with many items and poses security risks (users can tamper with data). Sessions are the recommended approach.

Modern 2026 Trends & Best Practices

  • AJAX Enhancements: Use JavaScript (e.g., Fetch API) to submit items asynchronously, updating the display without full page reloads. This improves UX.
  • Security: Always validate and sanitize input. Use htmlspecialchars() when outputting data to prevent XSS.
  • Database Finalization: When finalizing, use prepared statements to insert all items in a transaction for atomicity.
  • Frameworks: Laravel or Symfony offer built-in session handling and form validation, simplifying development.
  • Session Storage: For high-traffic apps, consider using Redis or Memcached for session storage instead of files.

This approach is robust, simple, and follows PHP best practices. Give it a try and let me know if you run into any issues!

:movie_camera: YouTube Video:

:books: Official Documentation & Reference Links: