Project Overview
A User Profile Management System allows users to create and manage their profiles, including personal information, profile pictures, and preferences. This project covers user authentication, profile editing, file uploads for profile pictures, and secure data handling using PHP and MySQL.
Prerequisites
Ensure you have the following:
- Web Server: Apache (using XAMPP, WAMP, or MAMP)
- PHP: Version 7.4 or higher
- MySQL: For database management
- Code Editor: VS Code, Sublime Text, PHPStorm, etc.
- Composer: For dependency management (optional)
- Basic Understanding of User Authentication and File Uploads
Step-by-Step Procedure
1. Setting Up the Development Environment
- Install XAMPP:
- Download from XAMPP Official Website.
- Follow the installation wizard and install it in the default directory.
- Start Apache and MySQL:
- Open the XAMPP Control Panel.
- Start the Apache and MySQL modules.
2. Creating the Database
- Access phpMyAdmin:
- Navigate to
http://localhost/phpmyadmin/
in your browser.
- Navigate to
- Create a New Database:
- Click on “New” in the left sidebar.
- Name the database
user_profiles
. - Choose “utf8mb4_unicode_ci” as the collation.
- Click “Create”.
- Create a
users
Table:- Select the
user_profiles
database. - Click on “New” to create a table.
- Define the table with the following fields:
- Click “Save”.
- Select the
3. Project Structure
Organize your project files as follows:
user-profile-management/
├── uploads/ # Directory to store profile pictures
├── assets/
│ ├── css/
│ │ └── styles.css
│ └── js/
│ └── scripts.js
├── config/
│ └── db.php
├── templates/
│ ├── header.php
│ └── footer.php
├── register.php
├── login.php
├── profile.php
├── edit_profile.php
├── logout.php
└── README.md
Note: Ensure that the uploads/
directory is writable by the web server.
4. Configuration
a. Database Connection (config/db.php
)
Create a file named db.php
inside the config
directory to handle database connections.
<?php
// config/db.php
$host = 'localhost';
$db = 'user_profiles';
$user = 'root'; // Default XAMPP MySQL user
$pass = ''; // Default XAMPP MySQL password is empty
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // Enable exceptions
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // Fetch associative arrays
PDO::ATTR_EMULATE_PREPARES => false, // Disable emulation
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
// Handle connection errors
http_response_code(500);
echo "Database connection failed.";
exit;
}
?>
5. Creating Reusable Templates
a. Header (templates/header.php
)
<?php
// templates/header.php
session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>User Profile Management</title>
<link rel="stylesheet" href="/user-profile-management/assets/css/styles.css">
</head>
<body>
<header>
<h1>User Profile Management</h1>
<nav>
<?php if (isset($_SESSION['user_id'])): ?>
<a href="/user-profile-management/profile.php">My Profile</a>
<a href="/user-profile-management/edit_profile.php">Edit Profile</a>
<a href="/user-profile-management/logout.php">Logout</a>
<?php else: ?>
<a href="/user-profile-management/login.php">Login</a>
<a href="/user-profile-management/register.php">Register</a>
<?php endif; ?>
</nav>
</header>
<main>
b. Footer (templates/footer.php
)
<?php
// templates/footer.php
?>
</main>
<footer>
<p>© <?php echo date("Y"); ?> Your Company Name</p>
</footer>
<script src="/user-profile-management/assets/js/scripts.js"></script>
</body>
</html>
6. Styling the Application (assets/css/styles.css
)
Add basic styles to enhance the appearance.
/* assets/css/styles.css */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
header, footer {
background-color: #0066cc;
color: #fff;
padding: 10px 20px;
}
header h1, footer p {
margin: 0;
}
nav a {
color: #fff;
margin-right: 15px;
text-decoration: none;
}
main {
padding: 20px;
}
form {
max-width: 500px;
margin: auto;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"],
input[type="email"],
input[type="password"],
textarea {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
button {
padding: 10px 15px;
background-color: #28a745;
color: #fff;
border: none;
cursor: pointer;
}
button:hover {
background-color: #218838;
}
.error {
background-color: #f8d7da;
color: #842029;
padding: 15px;
margin-bottom: 20px;
border: 1px solid #f5c2c7;
border-radius: 4px;
}
.success {
background-color: #d1e7dd;
color: #0f5132;
padding: 15px;
margin-bottom: 20px;
border: 1px solid #badbcc;
border-radius: 4px;
}
.profile-pic {
max-width: 150px;
border-radius: 50%;
}
7. User Registration (register.php
)
This page allows new users to create an account.
<?php
// register.php
require 'config/db.php';
require 'templates/header.php';
$errors = [];
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate inputs
$username = trim($_POST['username']);
$email = trim($_POST['email']);
$password = trim($_POST['password']);
$confirm_password = trim($_POST['confirm_password']);
if (empty($username)) {
$errors[] = 'Username is required.';
}
if (empty($email)) {
$errors[] = 'Email is required.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Invalid email format.';
}
if (empty($password)) {
$errors[] = 'Password is required.';
} elseif (strlen($password) < 6) {
$errors[] = 'Password must be at least 6 characters.';
}
if ($password !== $confirm_password) {
$errors[] = 'Passwords do not match.';
}
// Check if username or email already exists
if (empty($errors)) {
$stmt = $pdo->prepare('SELECT id FROM users WHERE username = ? OR email = ?');
$stmt->execute([$username, $email]);
if ($stmt->fetch()) {
$errors[] = 'Username or email already exists.';
}
}
if (empty($errors)) {
// Hash the password
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Insert into database
$stmt = $pdo->prepare('INSERT INTO users (username, email, password) VALUES (?, ?, ?)');
if ($stmt->execute([$username, $email, $hashed_password])) {
$success = 'Registration successful. You can now <a href="login.php">login</a>.';
// Clear form fields
$username = $email = $password = $confirm_password = '';
} else {
$errors[] = 'There was an error registering. Please try again.';
}
}
}
?>
<h2>Register</h2>
<?php if (!empty($errors)): ?>
<div class="error">
<ul>
<?php foreach($errors as $error): ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success">
<p><?php echo $success; ?></p>
</div>
<?php endif; ?>
<form action="register.php" method="POST">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username" value="<?php echo htmlspecialchars($username ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" value="<?php echo htmlspecialchars($email ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="password">Password (min 6 characters):</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group">
<label for="confirm_password">Confirm Password:</label>
<input type="password" id="confirm_password" name="confirm_password" required>
</div>
<button type="submit">Register</button>
</form>
<?php
require 'templates/footer.php';
?>
8. User Login (login.php
)
This page allows existing users to log in.
<?php
// login.php
require 'config/db.php';
require 'templates/header.php';
$errors = [];
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate inputs
$username = trim($_POST['username']);
$password = trim($_POST['password']);
if (empty($username)) {
$errors[] = 'Username is required.';
}
if (empty($password)) {
$errors[] = 'Password is required.';
}
if (empty($errors)) {
// Fetch user from database
$stmt = $pdo->prepare('SELECT id, password FROM users WHERE username = ?');
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
// Password is correct, start a session
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $username;
// Redirect to profile page
header('Location: profile.php');
exit;
} else {
$errors[] = 'Invalid username or password.';
}
}
}
?>
<h2>Login</h2>
<?php if (!empty($errors)): ?>
<div class="error">
<ul>
<?php foreach($errors as $error): ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success">
<p><?php echo htmlspecialchars($success); ?></p>
</div>
<?php endif; ?>
<form action="login.php" method="POST">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username" value="<?php echo htmlspecialchars($username ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Login</button>
</form>
<?php
require 'templates/footer.php';
?>
9. User Profile Page (profile.php
)
This is a protected page where users can view their profile information.
<?php
// profile.php
require 'config/db.php';
require 'templates/header.php';
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
// Fetch user information
$stmt = $pdo->prepare('SELECT username, email, profile_pic, bio, created_at FROM users WHERE id = ?');
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
if (!$user) {
echo "<p>User not found.</p>";
require 'templates/footer.php';
exit;
}
?>
<h2>My Profile</h2>
<?php if ($user['profile_pic']): ?>
<img src="uploads/<?php echo htmlspecialchars($user['profile_pic']); ?>" alt="Profile Picture" class="profile-pic">
<?php else: ?>
<img src="uploads/default.png" alt="Default Profile Picture" class="profile-pic">
<?php endif; ?>
<p><strong>Username:</strong> <?php echo htmlspecialchars($user['username']); ?></p>
<p><strong>Email:</strong> <?php echo htmlspecialchars($user['email']); ?></p>
<p><strong>Bio:</strong> <?php echo nl2br(htmlspecialchars($user['bio'] ?? '')); ?></p>
<p><strong>Member Since:</strong> <?php echo htmlspecialchars($user['created_at']); ?></p>
<a href="edit_profile.php">Edit Profile</a>
<?php
require 'templates/footer.php';
?>
10. Editing User Profile (edit_profile.php
)
This page allows users to update their profile information, including uploading a new profile picture.
<?php
// edit_profile.php
require 'config/db.php';
require 'templates/header.php';
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
// Fetch existing user information
$stmt = $pdo->prepare('SELECT username, email, profile_pic, bio FROM users WHERE id = ?');
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
if (!$user) {
echo "<p>User not found.</p>";
require 'templates/footer.php';
exit;
}
$errors = [];
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate inputs
$username = trim($_POST['username']);
$email = trim($_POST['email']);
$bio = trim($_POST['bio']);
if (empty($username)) {
$errors[] = 'Username is required.';
}
if (empty($email)) {
$errors[] = 'Email is required.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Invalid email format.';
}
// Handle profile picture upload if a new file is uploaded
if (isset($_FILES['profile_pic']) && $_FILES['profile_pic']['error'] !== UPLOAD_ERR_NO_FILE) {
if ($_FILES['profile_pic']['error'] === UPLOAD_ERR_OK) {
$fileTmpPath = $_FILES['profile_pic']['tmp_name'];
$originalName = $_FILES['profile_pic']['name'];
$fileSize = $_FILES['profile_pic']['size'];
$fileType = $_FILES['profile_pic']['type'];
$fileNameCmps = explode(".", $originalName);
$fileExtension = strtolower(end($fileNameCmps));
// Sanitize file name
$newFileName = md5(time() . $originalName) . '.' . $fileExtension;
// Allowed file extensions
$allowedfileExtensions = ['jpg', 'gif', 'png'];
if (in_array($fileExtension, $allowedfileExtensions)) {
// Directory in which the uploaded file will be moved
$uploadFileDir = './uploads/';
$dest_path = $uploadFileDir . $newFileName;
if(move_uploaded_file($fileTmpPath, $dest_path))
{
// Delete old profile picture if exists and not default
if ($user['profile_pic'] && $user['profile_pic'] !== 'default.png') {
unlink($uploadFileDir . $user['profile_pic']);
}
}
else
{
$errors[] = 'There was an error moving the uploaded file.';
}
}
else
{
$errors[] = 'Upload failed. Allowed file types: ' . implode(',', $allowedfileExtensions);
}
}
else
{
$errors[] = 'There is some error in the file upload. Please check the following error.<br>';
$errors[] = 'Error:' . $_FILES['profile_pic']['error'];
}
}
// Check if username or email already exists (excluding current user)
if (empty($errors)) {
$stmt = $pdo->prepare('SELECT id FROM users WHERE (username = ? OR email = ?) AND id != ?');
$stmt->execute([$username, $email, $_SESSION['user_id']]);
if ($stmt->fetch()) {
$errors[] = 'Username or email already exists.';
}
}
if (empty($errors)) {
// Update in database
if (isset($newFileName)) {
$stmt = $pdo->prepare('UPDATE users SET username = ?, email = ?, bio = ?, profile_pic = ? WHERE id = ?');
$result = $stmt->execute([$username, $email, $bio, $newFileName, $_SESSION['user_id']]);
} else {
$stmt = $pdo->prepare('UPDATE users SET username = ?, email = ?, bio = ? WHERE id = ?');
$result = $stmt->execute([$username, $email, $bio, $_SESSION['user_id']]);
}
if ($result) {
$success = 'Profile updated successfully.';
// Refresh user data
$stmt = $pdo->prepare('SELECT username, email, profile_pic, bio FROM users WHERE id = ?');
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
} else {
$errors[] = 'There was an error updating your profile. Please try again.';
}
}
}
?>
<h2>Edit Profile</h2>
<?php if (!empty($errors)): ?>
<div class="error">
<ul>
<?php foreach($errors as $error): ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success">
<p><?php echo htmlspecialchars($success); ?></p>
</div>
<?php endif; ?>
<form action="edit_profile.php" method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username" value="<?php echo htmlspecialchars($user['username']); ?>" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" value="<?php echo htmlspecialchars($user['email']); ?>" required>
</div>
<div class="form-group">
<label for="bio">Bio:</label>
<textarea id="bio" name="bio" rows="5"><?php echo htmlspecialchars($user['bio'] ?? ''); ?></textarea>
</div>
<div class="form-group">
<label for="profile_pic">Profile Picture:</label>
<input type="file" id="profile_pic" name="profile_pic" accept="image/*">
</div>
<button type="submit">Update Profile</button>
</form>
<?php
require 'templates/footer.php';
?>
11. User Logout (logout.php
)
This script logs the user out by destroying the session.
<?php
// logout.php
session_start();
session_unset();
session_destroy();
// Redirect to login page
header('Location: login.php');
exit;
?>
12. Testing the Application
- Access the Registration Page:
- Navigate to
http://localhost/user-profile-management/register.php
. - Fill in the registration form and submit.
- Verify that the user is registered and redirected appropriately.
- Navigate to
- Access the Login Page:
- Navigate to
http://localhost/user-profile-management/login.php
. - Enter the registered credentials and log in.
- Verify access to the profile page.
- Navigate to
- Edit Profile:
- Navigate to
http://localhost/user-profile-management/edit_profile.php
. - Update profile information and upload a new profile picture.
- Verify that changes are reflected on the profile page.
- Navigate to
- Logout:
- Click on “Logout”.
- Verify that the session is destroyed and access to protected pages is restricted.
13. Deployment Considerations
When deploying to a live server, consider the following:
- Secure File Uploads:
- Restrict file types and sizes to prevent malicious uploads.
- Store uploaded files outside the web root or restrict direct access using
.htaccess
.
- Implement HTTPS:
- Ensure your website uses HTTPS to encrypt data transmission.
- Protect Sensitive Data:
- Use environment variables or secure configuration methods for database credentials.
- Session Security:
- Implement secure session handling practices, such as regenerating session IDs upon login.
- Input Validation:
- Thoroughly validate and sanitize all user inputs to prevent SQL injection and XSS attacks.
- Error Reporting:
- Disable detailed error messages in production to prevent information leakage.
// In production, set error reporting to minimal ini_set('display_errors', 0); ini_set('log_errors', 1);
- Regular Backups:
- Implement regular backups of your database and uploaded files.