James Williams
Birmingham Newman University
jwilliams@staff.newman.ac.uk
3-hour session
Basic Database Connection:
<?php
// Database configuration
$host = "localhost";
$username = "root";
$password = "";
$database = "ecommerce";
// Create connection
try {
$pdo = new PDO("mysql:host=$host;dbname=$database", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
?>
Secure Database Queries:
// User registration with prepared statement
$stmt = $pdo->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
$username = $_POST['username'];
$email = $_POST['email'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
try {
$stmt->execute([$username, $email, $password]);
echo "User registered successfully";
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
Login Verification:
function authenticateUser($email, $password) {
global $pdo;
$stmt = $pdo->prepare("SELECT id, username, password FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
return true;
}
return false;
}
Complete Registration Process:
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$errors = validateRegistration($_POST);
if (empty($errors)) {
try {
$stmt = $pdo->prepare("INSERT INTO users (username, email, password, created_at) VALUES (?, ?, ?, NOW())");
$hashedPassword = password_hash($_POST['password'], PASSWORD_DEFAULT);
$stmt->execute([$_POST['username'], $_POST['email'], $hashedPassword]);
echo "Registration successful!";
} catch(PDOException $e) {
$errors[] = "Registration failed: " . $e->getMessage();
}
}
}
Create, Read, Update, Delete:
// CREATE - Insert new product
$stmt = $pdo->prepare("INSERT INTO products (name, price, description) VALUES (?, ?, ?)");
$stmt->execute([$name, $price, $description]);
// READ - Get all products
$stmt = $pdo->query("SELECT * FROM products ORDER BY name");
$products = $stmt->fetchAll();
// UPDATE - Modify product
$stmt = $pdo->prepare("UPDATE products SET price = ? WHERE id = ?");
$stmt->execute([$newPrice, $productId]);
// DELETE - Remove product
$stmt = $pdo->prepare("DELETE FROM products WHERE id = ?");
$stmt->execute([$productId]);
Database-Level Validation:
function checkEmailExists($email) {
global $pdo;
$stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE email = ?");
$stmt->execute([$email]);
return $stmt->fetchColumn() > 0;
}
function validateUniqueUsername($username) {
global $pdo;
$stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE username = ?");
$stmt->execute([$username]);
return $stmt->fetchColumn() == 0;
}
User Session Handling:
session_start();
// Check if user is logged in
function isLoggedIn() {
return isset($_SESSION['user_id']);
}
// Logout function
function logout() {
session_destroy();
header("Location: login.php");
exit();
}
// Protect pages
if (!isLoggedIn()) {
header("Location: login.php");
exit();
}
Database Error Management:
try {
$stmt = $pdo->prepare("INSERT INTO orders (user_id, total) VALUES (?, ?)");
$stmt->execute([$userId, $total]);
$orderId = $pdo->lastInsertId();
// Insert order items
foreach ($items as $item) {
$stmt = $pdo->prepare("INSERT INTO order_items (order_id, product_id, quantity) VALUES (?, ?, ?)");
$stmt->execute([$orderId, $item['id'], $item['quantity']]);
}
$pdo->commit();
echo "Order placed successfully";
} catch(PDOException $e) {
$pdo->rollback();
error_log("Database error: " . $e->getMessage());
echo "Order failed. Please try again.";
}
Time: 45 minutes
This task will help you master database integration techniques
Take a break, ask questions, or catch up on the previous task.
Next: Secondary slides and Task 2
Users Table:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Products Table:
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
price DECIMAL(10,2) NOT NULL,
stock INT DEFAULT 0,
image VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Product Listing with Search:
<?php
// Pagination
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$limit = 12;
$offset = ($page - 1) * $limit;
// Search functionality
$search = isset($_GET['search']) ? trim($_GET['search']) : '';
// Build query
$where = "WHERE 1=1";
$params = [];
if (!empty($search)) {
$where .= " AND (name LIKE ? OR description LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
}
// Get products
$stmt = $pdo->prepare("SELECT * FROM products $where ORDER BY created_at DESC LIMIT ? OFFSET ?");
$params[] = $limit;
$params[] = $offset;
$stmt->execute($params);
$products = $stmt->fetchAll();
?>
Image Upload Handling:
function handleImageUpload($file) {
$uploadDir = "uploads/";
$errors = [];
// Check if file was uploaded
if ($file["error"] !== UPLOAD_ERR_OK) {
$errors[] = "File upload failed";
return $errors;
}
// Validate file type
$allowedTypes = ["image/jpeg", "image/png", "image/gif"];
if (!in_array($file["type"], $allowedTypes)) {
$errors[] = "Invalid file type";
}
// Validate file size (2MB max)
if ($file["size"] > 2 * 1024 * 1024) {
$errors[] = "File too large (max 2MB)";
}
// Generate unique filename
$extension = pathinfo($file["name"], PATHINFO_EXTENSION);
$filename = uniqid() . "." . $extension;
$filepath = $uploadDir . $filename;
// Move uploaded file
if (!move_uploaded_file($file["tmp_name"], $filepath)) {
$errors[] = "Failed to save file";
}
return $errors;
}
Cart Database Tables:
CREATE TABLE cart (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
product_id INT,
quantity INT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (product_id) REFERENCES products(id)
);
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
total DECIMAL(10,2),
status ENUM('pending', 'processing', 'shipped', 'delivered') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
Database Indexes:
// Add indexes for better performance
CREATE INDEX idx_products_name ON products(name);
CREATE INDEX idx_products_price ON products(price);
CREATE INDEX idx_users_email ON users(email);
// Optimized query with joins
$stmt = $pdo->prepare("SELECT p.*, c.name as category_name FROM products p LEFT JOIN categories c ON p.category_id = c.id WHERE p.name LIKE ? ORDER BY p.created_at DESC LIMIT ? OFFSET ?");
Security Implementation:
// Secure password hashing
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
// Input sanitization
$username = htmlspecialchars(trim($_POST['username']));
$email = filter_var(trim($_POST['email']), FILTER_SANITIZE_EMAIL);
// CSRF protection
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('CSRF token validation failed');
}
Custom Error Handler:
function customErrorHandler($errno, $errstr, $errfile, $errline) {
$errorMessage = date('Y-m-d H:i:s') . " Error: [$errno] $errstr in $errfile on line $errline\n";
error_log($errorMessage, 3, "logs/error.log");
return true;
}
set_error_handler("customErrorHandler");
// Database error handling
try {
$stmt = $pdo->prepare("INSERT INTO products (name, price) VALUES (?, ?)");
$stmt->execute([$name, $price]);
} catch(PDOException $e) {
error_log("Database error: " . $e->getMessage());
echo "An error occurred. Please try again.";
}
Debug Functions:
// Debug function
function debug($data) {
echo "<pre>";
print_r($data);
echo "</pre>";
}
// Test database connection
function testConnection() {
global $pdo;
try {
$stmt = $pdo->query("SELECT 1");
echo "Database connection successful";
} catch(PDOException $e) {
echo "Database connection failed: " . $e->getMessage();
}
}
// Validate form data
function validateProductData($data) {
$errors = [];
if (empty($data['name'])) $errors[] = "Product name is required";
if (!is_numeric($data['price']) || $data['price'] <= 0) $errors[] = "Valid price is required";
return $errors;
}
Time: 45 minutes
This task will help you build a complete e-commerce database system
Advanced PHP Features - Object-oriented programming and advanced techniques