PHP – Use Case 4: Developing a Simple Blogging Platform
Project Overview
A Simple Blogging Platform allows users to create, read, update, and delete blog posts. This project encompasses content management, user authentication, and dynamic content rendering 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)
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
blog_platform
. - Choose “utf8mb4_unicode_ci” as the collation.
- Click “Create”.
- Create a
posts
Table:- Select the
blog_platform
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:
blog-platform/
├── assets/
│ ├── css/
│ │ └── styles.css
│ └── js/
│ └── scripts.js
├── config/
│ └── db.php
├── templates/
│ ├── header.php
│ └── footer.php
├── create_post.php
├── edit_post.php
├── delete_post.php
├── view_post.php
├── index.php
└── README.md
4. Configuration
a. Database Connection (config/db.php
)
<?php
// config/db.php
$host = 'localhost';
$db = 'blog_platform';
$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
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
?>
5. Creating Reusable Templates
a. Header (templates/header.php
)
<?php
// templates/header.php
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple Blogging Platform</title>
<link rel="stylesheet" href="/blog-platform/assets/css/styles.css">
</head>
<body>
<header>
<h1>Simple Blogging Platform</h1>
<nav>
<a href="/blog-platform/index.php">Home</a>
<a href="/blog-platform/create_post.php">Create New Post</a>
</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="/blog-platform/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: #333;
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: 600px;
margin: auto;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"],
textarea {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
button {
padding: 10px 15px;
background-color: #007BFF;
color: #fff;
border: none;
cursor: pointer;
}
button:hover {
background-color: #0069d9;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table, th, td {
border: 1px solid #ddd;
}
th, td {
padding: 12px;
text-align: left;
}
th {
background-color: #f4f4f4;
}
a {
color: #007BFF;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.error {
background-color: #f2dede;
color: #a94442;
padding: 15px;
margin-bottom: 20px;
border: 1px solid #ebccd1;
border-radius: 4px;
}
.success {
background-color: #dff0d8;
color: #3c763d;
padding: 15px;
margin-bottom: 20px;
border: 1px solid #d6e9c6;
border-radius: 4px;
}
7. Creating a New Post (create_post.php
)
This page allows users to create new blog posts.
<?php
// create_post.php
require 'config/db.php';
require 'templates/header.php';
$errors = [];
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate inputs
$title = trim($_POST['title']);
$content = trim($_POST['content']);
$author = trim($_POST['author']);
if (empty($title)) {
$errors[] = 'Post title is required.';
}
if (empty($content)) {
$errors[] = 'Post content is required.';
}
if (empty($author)) {
$errors[] = 'Author name is required.';
}
if (empty($errors)) {
// Insert into database
$stmt = $pdo->prepare('INSERT INTO posts (title, content, author) VALUES (?, ?, ?)');
if ($stmt->execute([$title, $content, $author])) {
$success = 'Post created successfully.';
// Clear form fields
$title = $content = $author = '';
} else {
$errors[] = 'There was an error creating the post. Please try again.';
}
}
}
?>
<h2>Create New Post</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="create_post.php" method="POST">
<div class="form-group">
<label for="title">Post Title:</label>
<input type="text" id="title" name="title" value="<?php echo htmlspecialchars($title ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="content">Post Content:</label>
<textarea id="content" name="content" rows="10" required><?php echo htmlspecialchars($content ?? ''); ?></textarea>
</div>
<div class="form-group">
<label for="author">Author Name:</label>
<input type="text" id="author" name="author" value="<?php echo htmlspecialchars($author ?? ''); ?>" required>
</div>
<button type="submit">Create Post</button>
</form>
<?php
require 'templates/footer.php';
?>
8. Viewing All Posts (index.php
)
This page lists all blog posts with options to view, edit, or delete them.
<?php
// index.php
require 'config/db.php';
require 'templates/header.php';
// Fetch all posts
$stmt = $pdo->query('SELECT * FROM posts ORDER BY created_at DESC');
$posts = $stmt->fetchAll();
?>
<h2>All Blog Posts</h2>
<?php if ($posts): ?>
<table>
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Author</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo htmlspecialchars($post['id']); ?></td>
<td><?php echo htmlspecialchars($post['title']); ?></td>
<td><?php echo htmlspecialchars($post['author']); ?></td>
<td><?php echo htmlspecialchars($post['created_at']); ?></td>
<td>
<a href="view_post.php?id=<?php echo $post['id']; ?>">View</a> |
<a href="edit_post.php?id=<?php echo $post['id']; ?>">Edit</a> |
<a href="delete_post.php?id=<?php echo $post['id']; ?>" onclick="return confirm('Are you sure you want to delete this post?');">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p>No posts found. <a href="create_post.php">Create a new post</a>.</p>
<?php endif; ?>
<?php
require 'templates/footer.php';
?>
9. Viewing a Single Post (view_post.php
)
This page displays the full content of a single blog post.
<?php
// view_post.php
require 'config/db.php';
require 'templates/header.php';
// Get post ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
// Fetch post details
$stmt = $pdo->prepare('SELECT * FROM posts WHERE id = ?');
$stmt->execute([$id]);
$post = $stmt->fetch();
if ($post):
?>
<h2><?php echo htmlspecialchars($post['title']); ?></h2>
<p><strong>Author:</strong> <?php echo htmlspecialchars($post['author']); ?></p>
<p><strong>Created At:</strong> <?php echo htmlspecialchars($post['created_at']); ?></p>
<div>
<?php echo nl2br(htmlspecialchars($post['content'])); ?>
</div>
<a href="index.php">Back to All Posts</a>
<?php
else:
echo "<p>Post not found.</p>";
endif;
require 'templates/footer.php';
?>
10. Editing Posts (edit_post.php
)
This page allows users to edit existing blog posts.
<?php
// edit_post.php
require 'config/db.php';
require 'templates/header.php';
$errors = [];
$success = '';
// Get post ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
// Fetch existing post
$stmt = $pdo->prepare('SELECT * FROM posts WHERE id = ?');
$stmt->execute([$id]);
$post = $stmt->fetch();
if (!$post) {
echo "<p>Post not found.</p>";
require 'templates/footer.php';
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate inputs
$title = trim($_POST['title']);
$content = trim($_POST['content']);
$author = trim($_POST['author']);
if (empty($title)) {
$errors[] = 'Post title is required.';
}
if (empty($content)) {
$errors[] = 'Post content is required.';
}
if (empty($author)) {
$errors[] = 'Author name is required.';
}
if (empty($errors)) {
// Update in database
$stmt = $pdo->prepare('UPDATE posts SET title = ?, content = ?, author = ? WHERE id = ?');
if ($stmt->execute([$title, $content, $author, $id])) {
$success = 'Post updated successfully.';
// Refresh post data
$stmt = $pdo->prepare('SELECT * FROM posts WHERE id = ?');
$stmt->execute([$id]);
$post = $stmt->fetch();
} else {
$errors[] = 'There was an error updating the post. Please try again.';
}
}
}
?>
<h2>Edit Post</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_post.php?id=<?php echo $id; ?>" method="POST">
<div class="form-group">
<label for="title">Post Title:</label>
<input type="text" id="title" name="title" value="<?php echo htmlspecialchars($post['title']); ?>" required>
</div>
<div class="form-group">
<label for="content">Post Content:</label>
<textarea id="content" name="content" rows="10" required><?php echo htmlspecialchars($post['content']); ?></textarea>
</div>
<div class="form-group">
<label for="author">Author Name:</label>
<input type="text" id="author" name="author" value="<?php echo htmlspecialchars($post['author']); ?>" required>
</div>
<button type="submit">Update Post</button>
</form>
<?php
require 'templates/footer.php';
?>
11. Deleting Posts (delete_post.php
)
This script handles the deletion of blog posts.
<?php
// delete_post.php
require 'config/db.php';
// Get post ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
// Delete post
$stmt = $pdo->prepare('DELETE FROM posts WHERE id = ?');
$stmt->execute([$id]);
// Redirect back to home page
header('Location: index.php');
exit;
?>
12. Testing the Application
- Access the Create Post Page:
- Navigate to
http://localhost/blog-platform/create_post.php
. - Fill in the form and submit.
- Verify that the post appears on the “All Blog Posts” page.
- Navigate to
- View a Single Post:
- Click on “View” next to a post.
- Ensure that the full content is displayed correctly.
- Edit a Post:
- Click on “Edit” next to a post.
- Modify the details and submit.
- Verify that the changes are reflected on the “All Blog Posts” page.
- Delete a Post:
- Click on “Delete” next to a post.
- Confirm the deletion.
- Ensure that the post is removed from the list.
13. Deployment Considerations
When deploying to a live server:
- Implement User Authentication: To restrict access to creating, editing, and deleting posts.
- Sanitize Inputs: Ensure all user inputs are properly sanitized to prevent SQL injection and XSS attacks.
- Use HTTPS: Ensure your website uses HTTPS for encrypted data transmission.
- Regular Backups: Implement regular backups of your database and files.
- 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);
- Update Dependencies: Keep PHP and all libraries updated to their latest versions to patch security vulnerabilities.