Database Setup
Before implementing the application, set up the MySQL database and table structure:
CREATE DATABASE IF NOT EXISTS student_db;
USE student_db;
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
gender VARCHAR(10),
interests VARCHAR(100),
location VARCHAR(50),
notes TEXT
);
Project Structure
| File | Purpose |
|---|---|
student_form.php |
Form for adding new student records |
student_list.php |
Displays all records with edit/delete options |
student_edit.php |
Form for modifying existing records |
handler.php |
Centralized CRUD operation processro |
Adding Records (student_form.php)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>New Student Entry</title>
</head>
<body>
<center>
<form id="entryForm" name="entryForm" method="post" action="handler.php?op=create">
<table>
<tr style="background: #555; color: white; font-size: 24px; text-align: center">
<td colspan="2">Student Information Entry</td>
</tr>
<tr>
<td>Name:</td>
<td><input id="studentName" name="studentName" type="text" required></td>
</tr>
<tr>
<td>Gender:</td>
<td>
<input type="radio" name="gender" value="Male" checked>Male
<input type="radio" name="gender" value="Female">Female
</td>
</tr>
<tr>
<td>Interests:</td>
<td><input type="text" name="interests" id="interests"></td>
</tr>
<tr>
<td>Location:</td>
<td>
<select id="location" name="location">
<option value="">-- Select Region --</option>
<option value="Shanghai">Shanghai</option>
<option value="Guangzhou">Guangzhou</option>
<option value="Beijing">Beijing</option>
</select>
</td>
</tr>
<tr>
<td>Notes:</td>
<td><textarea id="notes" name="notes" rows="5" cols="30"></textarea></td>
</tr>
<tr>
<td><input type="submit" value="Submit"></td>
<td><input type="reset" value="Reset"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
Displaying and Managing Records (student_list.php)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Student Roster</title>
<style>
th, td {
padding: 10px;
border: 1px solid #ddd;
}
th {
background-color: #f4f4f4;
}
</style>
<script>
function confirmDeletion(recordId) {
if (confirm("Are you sure you want to delete this record?")) {
window.location.href = 'handler.php?op=delete&id=' + recordId;
}
}
</script>
</head>
<body>
<center>
<h2>Student Information Directory</h2>
<table width="800" border="1" cellpadding="5" cellspacing="0">
<tr style="background: #444; color: white; font-size: 20px; text-align: center">
<td colspan="6">Student Records</td>
</tr>
<tr>
<th>Name</th>
<th>Gender</th>
<th>Interests</th>
<th>Location</th>
<th>Notes</th>
<th>Actions</th>
</tr>
<?php
try {
$db = new PDO("mysql:host=localhost;dbname=student_db;charset=utf8", "root", "password");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $err) {
die("Database connection failed: " . $err->getMessage());
}
$query = "SELECT * FROM students ORDER BY id DESC";
$result = $db->query($query);
while ($record = $result->fetch(PDO::FETCH_ASSOC)) {
echo "<tr>";
echo "<td>" . htmlspecialchars($record['name']) . "</td>";
echo "<td>" . htmlspecialchars($record['gender']) . "</td>";
echo "<td>" . htmlspecialchars($record['interests']) . "</td>";
echo "<td>" . htmlspecialchars($record['location']) . "</td>";
echo "<td>" . htmlspecialchars($record['notes']) . "</td>";
echo "<td>";
echo "<a href='javascript:confirmDeletion(" . $record['id'] . ")'>Delete</a> | ";
echo "<a href='student_edit.php?id=" . $record['id'] . "'>Edit</a>";
echo "</td>";
echo "</tr>";
}
?>
</table>
<p><a href="student_form.php">Add New Student</a></p>
</center>
</body>
</html>
Editing Records (student_edit.php)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Update Student Record</title>
</head>
<body>
<center>
<?php
if (!isset($_GET['id']) || empty($_GET['id'])) {
die("Invalid record ID specified.");
}
try {
$db = new PDO("mysql:host=localhost;dbname=student_db;charset=utf8", "root", "password");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $err) {
die("Database connection failed: " . $err->getMessage());
}
$recordId = intval($_GET['id']);
$stmt = $db->prepare("SELECT * FROM students WHERE id = :id");
$stmt->execute(['id' => $recordId]);
$student = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$student) {
die("Record not found in database.");
}
?>
<form id="updateForm" name="updateForm" method="post" action="handler.php?op=update">
<input type="hidden" name="recordId" value="<?php echo $student['id']; ?>">
<table>
<tr style="background: #555; color: white; font-size: 24px; text-align: center">
<td colspan="2">Modify Student Information</td>
</tr>
<tr>
<td>Name:</td>
<td><input id="studentName" name="studentName" type="text"
value="<?php echo htmlspecialchars($student['name']); ?>" required></td>
</tr>
<tr>
<td>Gender:</td>
<td>
<input type="radio" name="gender" value="Male"
<?php echo $student['gender'] === 'Male' ? 'checked' : ''; ?>>Male
<input type="radio" name="gender" value="Female"
<?php echo $student['gender'] === 'Female' ? 'checked' : ''; ?>>Female
</td>
</tr>
<tr>
<td>Interests:</td>
<td><input type="text" name="interests" id="interests"
value="<?php echo htmlspecialchars($student['interests']); ?>"></td>
</tr>
<tr>
<td>Location:</td>
<td>
<select id="location" name="location">
<option value="">-- Select Region --</option>
<option value="Shanghai"
<?php echo $student['location'] === 'Shanghai' ? 'selected' : ''; ?>>Shanghai</option>
<option value="Guangzhou"
<?php echo $student['location'] === 'Guangzhou' ? 'selected' : ''; ?>>Guangzhou</option>
<option value="Beijing"
<?php echo $student['location'] === 'Beijing' ? 'selected' : ''; ?>>Beijing</option>
</select>
</td>
</tr>
<tr>
<td>Notes:</td>
<td><textarea id="notes" name="notes" rows="5" cols="30">
<?php echo htmlspecialchars($student['notes']); ?>
</textarea></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Save Changes"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
CRUD Handler (handler.php)
<?php
try {
$db = new PDO("mysql:host=localhost;dbname=student_db;charset=utf8", "root", "password");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e) {
die("Connection failed: " . $e->getMessage());
}
$operation = $_GET['op'] ?? $_POST['op'] ?? '';
switch ($operation) {
case 'create':
$name = trim($_POST['studentName']);
$gender = $_POST['gender'] ?? 'Male';
$interests = trim($_POST['interests']);
$location = $_POST['location'] ?? '';
$notes = trim($_POST['notes']);
$insertSql = "INSERT INTO students (name, gender, interests, location, notes)
VALUES (:name, :gender, :interests, :location, :notes)";
$stmt = $db->prepare($insertSql);
$stmt->execute([
':name' => $name,
':gender' => $gender,
':interests' => $interests,
':location' => $location,
':notes' => $notes
]);
if ($stmt->rowCount() > 0) {
header("Location: student_list.php?status=added");
exit;
} else {
echo "<script>alert('Failed to add record'); history.back();</script>";
}
break;
case 'delete':
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if ($id > 0) {
$deleteSql = "DELETE FROM students WHERE id = :id";
$stmt = $db->prepare($deleteSql);
$stmt->execute([':id' => $id]);
if ($stmt->rowCount() > 0) {
header("Location: student_list.php?status=deleted");
exit;
}
}
echo "<script>alert('Deletion failed or record not found'); history.back();</script>";
break;
case 'update':
$id = intval($_POST['recordId']);
$name = trim($_POST['studentName']);
$gender = $_POST['gender'] ?? 'Male';
$interests = trim($_POST['interests']);
$location = $_POST['location'] ?? '';
$notes = trim($_POST['notes']);
$updateSql = "UPDATE students SET
name = :name,
gender = :gender,
interests = :interests,
location = :location,
notes = :notes
WHERE id = :id";
$stmt = $db->prepare($updateSql);
$stmt->execute([
':name' => $name,
':gender' => $gender,
':interests' => $interests,
':location' => $location,
':notes' => $notes,
':id' => $id
]);
if ($stmt->rowCount() > 0) {
header("Location: student_list.php?status=updated");
exit;
} else {
echo "<script>alert('No changes made or update failed'); history.back();</script>";
}
break;
default:
header("Location: student_list.php");
exit;
}
?>
Security Considerations
SQL Injection Prevention:
The refactored code uses PDO prepared statements exclusively. Placeholder markers (:name, :id, etc.) ensure user input is never concatenated directly into SQL queries, preventing injection attacks.
XSS Prevention:
The htmlspecialchars() function escapes output when displaying user-submitted data in HTML context, neutralizing potential Cross-Site Scripting vectors.
Input Validation:
intval()converts numeric parameters to integers before database operationstrim()removes extraneous whitespace from text inputs- Required field validation on the form prevents empty submissions
Key Improvements Over Procedural Approach
| Aspect | Original Code | Refactored Code |
|---|---|---|
| Database abstraction | Procedural mysql_* style |
PDO with prepared statements |
| Error handling | Basic try-catch | PDO exception modes enabled |
| Parameter handling | String interpolation | Bound parameters |
| Output encoding | None | htmlspecialchars() throughout |
| Code organization | Scattered across files | Centralized handler |
Database Connection Pattern
Establish the PDO connection once and reuse the $db object across all operations:
$dsn = "mysql:host=localhost;dbname=student_db;charset=utf8";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, 'root', 'password', $options);
This configuration enables exception-based error handling, sets associative array fetching as default, and disables emulated prepares for security.