A feature-rich blogging platform built with PHP, MySQL, and Twig templating engine. This project demonstrates modern web development practices including MVC architecture, security best practices, and interactive user experiences.
- Overview
- Features
- Technology Stack
- Project Structure
- Installation & Setup
- Database Configuration
- Security Features
- API Endpoints
- Routing System
- Known Limitations
- Future Enhancements
- Development Notes
- Author
This is a full-featured blog management system that allows users to create, read, update, and delete blog posts. The application includes user authentication, rich text editing, social features like following, comments, likes, and saved posts. Built as part of a Full Stack Development coursework, it demonstrates practical implementation of web security, database design, and modern PHP development patterns.
- User Registration & Authentication with password hashing (bcrypt)
- User Profiles with bio and avatar support
- Profile Editing for authenticated users
- Follow/Unfollow System to connect with other writers
- User Statistics showing follower count, following count, and total blogs
- Create Blogs with rich text editor (Quill.js integration)
- Edit & Delete Blogs (owner-only access)
- Blog Categories for content organization
- Thumbnail URLs for visual appeal
- Auto-generated Slugs for SEO-friendly URLs
- View Counter to track blog popularity
- Excerpt Generation for blog previews
- Comments System on blog posts
- Like/Unlike Blogs with real-time counter
- Save/Bookmark Blogs for later reading
- Following Feed to view blogs from followed users
- "For You" Feed displaying all blogs
- Real-time Search with autocomplete
- Tag-based Filtering for content discovery
- Author-based Filtering to explore writer portfolios
- Load More Pagination for better performance
- Rich Text Editor with Quill.js
- HTML Sanitization using HTMLPurifier
- Responsive Design with theme toggle (light/dark mode)
- Reading Time Estimation
- Related Posts from same author
- PHP 7.4+ - Server-side scripting
- MySQL/MariaDB - Relational database
- Twig 3.x - Template engine for views
- PSR-4 Autoloading - Modern PHP class loading
- Vanilla JavaScript - Client-side interactions
- Quill.js - Rich text editor
- CSS3 - Custom styling with theme support
- Responsive Design - Mobile-friendly layouts
- HTMLPurifier - XSS prevention and HTML sanitization
- Custom CSRF Protection - Token-based request validation
- Custom Captcha - Bot prevention on registration/login
- Composer - PHP dependency management
- Git - Version control
Write/
├── composer.json # PHP dependencies
├── index.php # Application entry point
├── seed.sql # Sample data for testing
├── table.sql # Database schema
├── assets/
│ ├── css/
│ │ └── style.css # Main stylesheet with theme support
│ └── js/
│ ├── auth-validation.js # Client-side form validation
│ ├── autoComplete.js # Search autocomplete functionality
│ ├── interactions.js # Like, save, follow interactions
│ ├── quill-handler.js # Rich text editor integration
│ └── theme-toggle.js # Dark/light mode toggle
├── cache/
│ ├── htmlpurifier/ # HTMLPurifier cache files
│ └── templates/ # Twig compiled template cache
├── config/
│ └── db.php # Database configuration
├── logs/
│ └── php_error.log # Application error logs
├── src/
│ ├── Router.php # Custom routing system
│ ├── TemplateEngine.php # Twig wrapper
│ ├── Controllers/
│ │ ├── BaseController.php # Abstract base controller
│ │ ├── BlogController.php # Blog CRUD operations
│ │ ├── HomeController.php # Homepage & about page
│ │ └── UserController.php # User authentication & profile
│ ├── Exceptions/
│ │ ├── AuthenticationException.php
│ │ ├── ModelException.php
│ │ ├── NotFoundException.php
│ │ └── ValidationException.php
│ ├── Models/
│ │ ├── Blog.php # Blog model
│ │ ├── Comment.php # Comment model
│ │ ├── ModelInterface.php # Model contract
│ │ └── User.php # User model
│ └── Utils/
│ ├── Captcha.php # Simple math captcha
│ ├── Csrf.php # CSRF token generation/verification
│ ├── HtmlSanitizer.php # HTML purification wrapper
│ └── Validator.php # Input validation utilities
├── templates/ # Twig view templates
│ ├── auth_base.twig # Authentication pages layout
│ ├── base.twig # Main application layout
│ ├── blogs/
│ │ ├── create.twig # Blog creation form
│ │ ├── edit.twig # Blog edit form
│ │ ├── index.twig # Blog listing page
│ │ ├── stats.twig # Blog statistics
│ │ ├── success.twig # Success message page
│ │ ├── user_blogs.twig # User's blogs view
│ │ ├── user_stories.twig # User's stories view
│ │ └── view.twig # Single blog view
│ ├── components/
│ │ ├── _article_card.twig # Article card partial
│ │ ├── _nav.twig # Navigation bar
│ │ ├── _sidebar_left.twig # Left sidebar
│ │ ├── _story_card.twig # Story card partial
│ │ └── blog_card.twig # Blog card partial
│ ├── errors/
│ │ ├── 400.twig # Bad request error
│ │ ├── 401.twig # Unauthorized error
│ │ ├── 404.twig # Not found error
│ │ ├── 422.twig # Validation error
│ │ ├── 500.twig # Server error
│ │ └── 500_static.html # Static fallback error page
│ ├── home/
│ │ ├── about.twig # About page
│ │ └── index.twig # Homepage
│ └── users/
│ ├── edit.twig # Profile edit form
│ ├── login.twig # Login page
│ ├── profile.twig # User profile page
│ ├── register.twig # Registration page
│ └── success.twig # Registration success
├── uploads/ # User-uploaded files directory
└── vendor/ # Composer dependencies
├── autoload.php # Composer autoloader
├── composer/ # Composer metadata
├── ezyang/
│ └── htmlpurifier/ # HTML sanitization library
├── symfony/ # Symfony components
│ ├── deprecation-contracts/
│ ├── polyfill-ctype/
│ └── polyfill-mbstring/
└── twig/
└── twig/ # Twig templating engine
- PHP 7.4 or higher
- MySQL 5.7+ or MariaDB 10.3+
- Composer (for dependency management)
- Apache/Nginx web server
- mod_rewrite enabled (for Apache)
git clone <repository-url>
cd Courseworkcomposer installThis will install:
twig/twig- Template engineezyang/htmlpurifier- HTML sanitization
- Create the database:
mysql -u root -p- Import the schema:
source table.sql- Import sample data (optional):
source seed.sqlThe table.sql file creates:
user- User accountsblog- Blog postscomment- Blog commentslikes- Blog likesfollows- User follow relationshipssaved_blogs- Bookmarked blogs
Edit config/db.php:
<?php
$host = 'localhost';
$dbname = 'blogManagement';
$username = 'your_username';
$password = 'your_password';
$conn = new mysqli($host, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}chmod -R 755 cache/
chmod -R 755 logs/
chmod -R 755 uploads/Create .htaccess in project root:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]location / {
try_files $uri $uri/ /index.php?$query_string;
}In index.php and relevant templates, adjust:
$basePath = '/~subdirectory'; // Change to your subdirectoryFor local development:
$basePath = ''; // Empty for root directoryhttp://localhost/
# or
http://localhost/~subdirectory/
Users Table:
- Stores user credentials, profile info
- Password hashing with bcrypt
- Unique username and email constraints
Blogs Table:
- User-generated content with rich HTML
- SEO-friendly slugs
- Thumbnail URLs and categories
- View counter for analytics
Comments Table:
- Nested under specific blogs
- Linked to users with cascade delete
Likes Table:
- Many-to-many relationship (user ↔ blog)
- Unique constraint prevents duplicate likes
Follows Table:
- Self-referencing user relationships
- Follower/following system
Saved Blogs Table:
- User bookmarks for blogs
- Unique constraint per user-blog pair
All relationships use ON DELETE CASCADE to maintain referential integrity.
- Password hashing using
password_hash()with bcrypt algorithm - Session-based authentication
- Secure session configuration:
- Custom session name to prevent conflicts
- HttpOnly cookies
- SameSite=Strict policy
- HTTPS-only cookies (when available)
- Path-restricted sessions
- Token-based CSRF validation on all POST requests
- Tokens generated using cryptographically secure
random_bytes() hash_equals()for timing-attack resistant comparison
- HTMLPurifier sanitizes all user-generated HTML content
- Whitelist-based approach for allowed HTML tags and attributes
- Twig auto-escaping enabled by default
- Custom sanitization for rich text editor content
- Prepared statements used throughout
- Parameterized queries with mysqli
- No raw user input in SQL queries
- Simple math challenge on registration and login
- Session-based validation
- Prevents automated bot registrations
- Server-side validation for all user inputs
- Email format validation
- Password strength requirements
- String length constraints
- URL sanitization for external links
Implemented in index.php:
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin- Production mode: errors logged, not displayed
- Custom error pages for 400, 401, 404, 422, 500
- Detailed logging to
logs/php_error.log
- Owner-only blog editing and deletion
- Profile editing restricted to account owner
- Authentication checks on protected routes
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
Homepage with blog feed |
| GET | /about |
About page |
| GET | /blogs |
All blogs listing |
| GET | /blogs/{id} |
View single blog (by ID or slug) |
| GET | /@{username} |
User profile page |
| GET | /tag/{tag} |
Blogs filtered by tag |
| Method | Endpoint | Description |
|---|---|---|
| GET | /auth/register |
Registration form |
| POST | /auth/register |
Process registration |
| GET | /auth/login |
Login form |
| POST | /auth/login |
Process login |
| GET | /auth/logout |
Logout user |
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/{id}/edit |
Edit profile form |
| POST | /users/{id}/edit |
Update profile |
| POST | /users/{id}/follow |
Toggle follow status |
| GET | /me/stories |
User's own blogs |
| GET | /me/saved |
User's saved blogs |
| Method | Endpoint | Description |
|---|---|---|
| GET | /blogs/create |
Create blog form |
| POST | /blogs/create |
Save new blog |
| GET | /blogs/{id}/edit |
Edit blog form |
| POST | /blogs/{id}/edit |
Update blog |
| POST | /blogs/{id}/delete |
Delete blog |
| POST | /blogs/{id}/comment |
Add comment |
| POST | /blogs/{id}/save |
Toggle bookmark |
| POST | /blogs/{id}/like |
Toggle like |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/blogs |
JSON list of blogs (with pagination) |
| GET | /api/blogs/search?q={query} |
Search blogs (autocomplete) |
The application uses a custom-built routing system (src/Router.php) that supports:
- Static routes:
/about,/blogs - Dynamic routes:
/blogs/{id},/@{username},/tag/{tag} - HTTP method separation: GET vs POST
- Subdirectory deployment: Automatically handles base path
- 404 handling: Custom error page for unmatched routes
// Static route
$router->get('/blogs', 'BlogController@index');
// Dynamic route with parameter
$router->get('/blogs/{id}', 'BlogController@view');
// Controller@method syntax
// Resolves to: BlogController->view($id)-
No File Upload for Avatars/Thumbnails
- Only URL-based images supported
- No local file storage implementation due to server constraints
- Users must provide external image URLs
-
Basic Pagination
- "Load More" button without numbered pages
- No jump-to-page functionality
-
Limited Search
- Simple title-based search
- No full-text search on content
- No advanced filters (date range, author, etc.)
-
No Email Verification
- Users can register without email confirmation
- Password reset not implemented
-
No Admin Panel
- No administrative interface
- No user management system
- No content moderation tools
-
Single Database Connection
- Global
$connvariable - No connection pooling
- Not suitable for high concurrency
- Global
-
Limited Comment Features
- No nested replies
- No comment editing/deletion
- No comment pagination
-
No Notifications
- No real-time notifications
- No email alerts for follows, comments, or likes
-
File Upload System
- Local avatar uploads
- Blog thumbnail uploads
- Image optimization and validation
-
Advanced Search
- Full-text search with MySQL FULLTEXT indexes
- Multi-field filtering
- Search suggestions
-
Email Integration
- Account verification emails
- Password reset functionality
- Notification emails for interactions
-
Admin Dashboard
- User management
- Content moderation
- Analytics and reporting
-
Enhanced Comments
- Nested comment threads
- Edit/delete comments
- Comment reactions
-
Social Features
- Real-time notifications
- User mentions in comments
- Share to social media
-
Content Improvements
- Draft saving
- Scheduled publishing
- Multi-author blogs
- Content versioning
-
Performance Optimization
- Redis/Memcached caching
- Database query optimization
- CDN integration for static assets
-
API Expansion
- RESTful API for mobile apps
- OAuth integration
- Rate limiting
- PSR-4 autoloading for classes
- Namespaced code under
Aaditya\Cms - MVC architecture pattern
- Prepared statements for database queries
- Exception-based error handling
- Theme Toggle: Persistent dark/light mode
- Real-time Validation: Client-side form validation
- AJAX Interactions: Like, save, follow without page reload
- Search Autocomplete: Instant search results
- Infinite Scroll: Load more blogs dynamically
- base.twig: Main layout with navigation
- auth_base.twig: Authentication pages layout
- Component partials: Reusable UI elements
- Error templates: Custom error pages
For Shared Hosting:
- Update
session_name()to avoid conflicts - Set correct
session_set_cookie_params()path - Adjust
$basePathin Router.php - Ensure proper file permissions
For Production:
- Disable error display:
ini_set('display_errors', 0) - Enable HTTPS and update security headers
- Use environment variables for sensitive config
- Implement proper backup strategy
- Set up monitoring and logging
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
Note: Requires JavaScript enabled for interactive features.
This is a coursework project for educational purposes.
Aaditya Thapa
GitHub: @adgator101
Email: aadityathapa977@gmail.com
- Twig - Flexible template engine
- HTMLPurifier - XSS protection
- Quill.js - Rich text editing
- PHP Community - Excellent documentation
For issues, questions, or contributions related to this project, please open an issue in the repository or contact the author directly.
Last Updated: February 2026