Skip to content

Master-Details in PHP

  • Master-Details is a UI pattern that displays a list of items (master) alongside detailed information about a selected item (details).
  • Common examples include email clients, product catalogs, and user management systems.

There are several ways to implement the Master-Details pattern. The examples below use the URL parameter approach.

Both master list and details display on the same page:

  • Master list always visible.
  • Details panel updates based on selection.
  • Uses URL parameters for item selection.

Master and details on different pages:

  • Master page shows the list.
  • Clicking an item navigates to details page.
  • Requires back navigation to return to list.

Dynamic loading without page refresh:

  • Master list loads initially.
  • Details load via JavaScript/AJAX.
  • Smoother user experience.

Design tables with a clear relationship between master and detail records:

CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
category VARCHAR(100),
description TEXT,
price DECIMAL(10, 2)
);

Display items in a summary format with links to view details:

// Connect to database
$pdo = new PDO('mysql:host=localhost;dbname=store', 'user', 'password');
// Fetch only the columns needed for the list
$stmt = $pdo->query("SELECT id, name, category FROM products");
$products = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Display each product as a link
foreach ($products as $product) {
$id = htmlspecialchars($product['id']);
$name = htmlspecialchars($product['name']);
echo "<a href='?id=$id'>$name</a><br>";
}

Use URL parameters to identify which item to display. Always validate the input:

// Validate the ID parameter (must be a positive integer)
$selected_id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($selected_id) {
// Use prepared statement to prevent SQL injection
$stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?");
$stmt->execute([$selected_id]);
$selected_item = $stmt->fetch(PDO::FETCH_ASSOC);
// Handle case where item doesn't exist
if (!$selected_item) {
echo "<p>Product not found.</p>";
}
}

Show comprehensive information about the selected item with proper output escaping:

if (isset($selected_item) && $selected_item) {
echo "<h2>" . htmlspecialchars($selected_item['name']) . "</h2>";
echo "<p>Category: " . htmlspecialchars($selected_item['category']) . "</p>";
echo "<p>Price: $" . htmlspecialchars($selected_item['price']) . "</p>";
echo "<p>" . htmlspecialchars($selected_item['description']) . "</p>";
echo "<a href='?'>Back to list</a>";
}

Allow users to move between items:

// Get adjacent product IDs
$stmt = $pdo->prepare("SELECT id FROM products WHERE id < ? ORDER BY id DESC LIMIT 1");
$stmt->execute([$selected_id]);
$prev = $stmt->fetch();
$stmt = $pdo->prepare("SELECT id FROM products WHERE id > ? ORDER BY id ASC LIMIT 1");
$stmt->execute([$selected_id]);
$next = $stmt->fetch();
// Display navigation links
if ($prev) echo "<a href='?id={$prev['id']}'>Previous</a> ";
if ($next) echo "<a href='?id={$next['id']}'>Next</a>";

Enable users to filter the master list:

// Get filter parameters
$search = $_GET['search'] ?? '';
$category = $_GET['category'] ?? '';
// Build query with filters
$sql = "SELECT id, name, category FROM products WHERE 1=1";
$params = [];
if ($search) {
$sql .= " AND name LIKE ?";
$params[] = "%$search%";
}
if ($category) {
$sql .= " AND category = ?";
$params[] = $category;
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$products = $stmt->fetchAll(PDO::FETCH_ASSOC);

  1. Not validating the ID parameter - Using $_GET['id'] directly allows SQL injection. Always use filter_input() or validate manually.

  2. Missing output escaping - Displaying database values without htmlspecialchars() creates XSS vulnerabilities.

  3. Loading all data in the master list - Fetching every column for the list view wastes memory. Select only what you need to display.

  4. Not handling missing items - Users can manually change the URL. Always check if the requested item exists before displaying it.

  5. Using string concatenation in queries - This creates SQL injection risks. Use prepared statements with parameter binding.


  • Load only necessary columns for the master list.
  • Fetch detailed data only when an item is selected.
  • Implement pagination for large datasets.
  • Add database indexes on frequently queried fields (id, category).
  • Highlight the currently selected item in the list.
  • Provide clear navigation (back to list, previous/next).
  • Maintain filter state when viewing details.