A professional web application built with pure PHP following MVC architecture, OOP principles, PSR-4 autoloading, and PSR-1 naming conventions. Features user authentication, validated form submission, and comprehensive reportingβall containerized with Docker for easy deployment.
π Documentation β’ π― Features β’ π³ Docker Setup β’ ποΈ Architecture
Clean and intuitive registration interface with real-time validation
Secure authentication with session management
Interactive form with dynamic item addition and validation
Comprehensive reporting with filtering options
| Category | Technology |
|---|---|
| Backend | PHP 8.1 |
| Database | MySQL 8.0 |
| Frontend | JavaScript (Vanilla), HTML5, CSS3 |
| Containerization | Docker & Docker Compose |
| Dependency Management | Composer |
| Database Management | phpMyAdmin |
| Architecture | MVC, Repository Pattern, Service Layer |
| OOP Principles | All 4 Pillars Implemented |
| Autoloading | PSR-4 |
| Coding Standards | PSR-1, PSR-12 |
This project follows a clean, layered architecture that separates concerns and promotes maintainability, testability, and scalability.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLIENT REQUEST β
β (Browser β HTTP Request) β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PUBLIC ENTRY POINT β
β (public/signup.php, etc.) β
β - Composer Autoload β
β - Session Management β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CONTROLLER β
β (AuthController, SubmissionController) β
β - Handle HTTP Request β
β - Route to Appropriate Method β
β - Authentication Check β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β VALIDATOR β
β (UserSignupValidator, SubmissionValidator) β
β - Validate Input Data β
β - Apply Business Rules β
β - Return Errors if Invalid β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SERVICE β
β (AuthService, SubmissionService) β
β - Execute Business Logic β
β - Coordinate Operations β
β - Handle Transactions β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β REPOSITORY β
β (UserRepository, SubmissionRepository) β
β - Database Operations (CRUD) β
β - Query Building β
β - Data Mapping β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DATABASE MODEL β
β (Database Singleton) β
β - PDO Connection β
β - Query Execution β
β - Transaction Management β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MySQL DATABASE β
β - Data Persistence β
β - ACID Compliance β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ (Response flows back up)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β VIEW β
β (dashboard.php, reports.php) β
β - Render HTML β
β - Display Data β
β - User Interface β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLIENT RESPONSE β
β (Browser renders page) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
This project implements the Model-View-Controller pattern:
- Database.php: Singleton pattern for database connections
- Repositories: Handle all database operations (CRUD)
- Services: Contain business logic and orchestrate operations
- app/Views/: Reusable view components
- public/: Public-facing pages
- JavaScript files: Client-side validation and interactivity
- AuthController: Handles authentication (signup, login, logout)
- SubmissionController: Manages form submissions and reports
- AbstractController: Base controller with shared functionality
The Repository Pattern abstracts data access and provides a collection-like interface:
AbstractRepository (Base CRUD Operations)
β
UserRepository (User-specific queries)
- findByEmail()
- emailExists()
- verifyPassword()
SubmissionRepository (Submission-specific queries)
- getFiltered()
- findByReceiptId()
- generateHashKey()The Service Layer contains business logic and coordinates between controllers and repositories:
AuthService
- register(name, email, password)
- login(email, password)
- Coordinates: Validator β Repository
SubmissionService
- createSubmission(data)
- getFilteredSubmissions(filters)
- Coordinates: Validator β Repository β Business RulesBenefits:
- Separates business logic from controllers
- Reusable across multiple entry points
- Easier to test
- Follows Single Responsibility Principle
This project is a comprehensive demonstration of Object-Oriented Programming principles applied to real-world web development.
Definition: Bundling data and methods together while restricting direct access.
Implementation:
class AbstractRepository {
protected $connection;
protected $table;
protected function query($sql, $params) {
}
}Examples in Project:
AuthService: Private properties$userRepository,$errors,$responseAbstractController: Protected session management methods- All repositories: Protected database connection
Definition: Child classes inherit properties and methods from parent classes.
Implementation:
// Parent provides base CRUD operations
AbstractRepository
β
UserRepository extends AbstractRepository
- Inherits: all(), findById(), create(), update(), delete()
- Adds: findByEmail(), emailExists()Class Hierarchies:
AbstractController
βββ AuthController
βββ SubmissionController
AbstractRepository
βββ UserRepository
βββ SubmissionRepository
AbstractValidator
βββ UserSignupValidator
βββ UserLoginValidator
βββ SubmissionValidator
Definition: Same method name behaves differently in different classes.
Implementation:
// Parent method
class AbstractRepository {
public function create(array $data): bool {
// Generic create
}
}
// Child overrides with specific behavior
class UserRepository extends AbstractRepository {
public function create(array $data): bool {
$data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
return parent::create($data); // Calls parent with hashed password
}
}Examples:
- All validators implement
validateRules()differently - Controllers implement request handlers polymorphically
- Services implement
execute()with different business logic
Definition: Hiding implementation details while exposing essential features.
Implementation:
interface RepositoryInterface {
public function all(): array;
public function findById(int $id): ?array;
public function create(array $data): bool;
// Defines WHAT, not HOW
}
abstract class AbstractValidator implements ValidatorInterface {
abstract protected function validateRules(array $data): void;
// Forces children to implement specific validation
}Interfaces in Project:
RepositoryInterface: Defines data access contractValidatorInterface: Defines validation contractAuthenticationInterface: Defines auth operations contractServiceInterface: Defines service operations contract
RepositoryInterface (Contract)
β
AbstractRepository (Implementation + Helpers)
βββ UserRepository (User-specific operations)
βββ SubmissionRepository (Submission-specific operations)
ValidatorInterface (Contract)
β
AbstractValidator (Base validation + Helpers)
βββ UserSignupValidator
βββ UserLoginValidator
βββ SubmissionValidator
AbstractController (Base functionality)
βββ AuthController (Authentication operations)
βββ SubmissionController (Submission operations)
class Database {
private static $instance = null;
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}Purpose: Ensures only one database connection exists.
Purpose: Abstracts data layer and provides collection-like interface.
Purpose: Separates business logic from controllers.
class AuthController extends AbstractController {
private $authService;
private $validator;
public function __construct(AuthService $authService, UserSignupValidator $validator) {
$this->authService = $authService;
$this->validator = $validator;
}
}Purpose: Loose coupling and easier testing.
Purpose: Separation of concerns.
This project uses Docker to containerize the entire application stack, making it portable, consistent, and easy to deploy across different environments.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Docker Host β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β roxnor_network (Bridge) β β
β β β β
β β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β β
β β β PHP App β β MySQL β β phpMyAdmin β β β
β β β Container β β Container β β Container β β β
β β β β β β β β β β
β β β Port: 8080 β β Port: 3307 β β Port: 8081 β β β
β β β β β β β β β β
β β β PHP 8.1 β β MySQL 8.0 β β phpMyAdmin β β β
β β β Apache β β β β Latest β β β
β β β Composer β β β β β β β
β β ββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββ¬ββββββββ β β
β β β β β β β
β β βββββββββββββββββββ΄ββββββββββββββββββ β β
β β Inter-container β β
β β Communication β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Docker Volumes (Persistent) β β
β β β β
β β β’ db_data β MySQL data persistence β β
β β β’ ./:/var/www/html β App code mounting β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
roxnor/
βββ app/ # Application logic
β βββ Abstracts/ # Abstract base classes
β β βββ AbstractController.php # Base controller functionality
β β βββ AbstractRepository.php # Base CRUD operations
β β βββ AbstractValidator.php # Base validation helpers
β βββ Contracts/ # Interfaces (Abstraction)
β β βββ AuthenticationInterface.php
β β βββ DatabaseInterface.php
β β βββ RepositoryInterface.php
β β βββ ServiceInterface.php
β β βββ ValidatorInterface.php
β βββ Controllers/ # Request handlers
β β βββ AuthController.php # Authentication logic
β β βββ SubmissionController.php # Submission logic
β βββ Models/ # Database models
β β βββ Database.php # Singleton DB connection
β βββ Repositories/ # Data access layer
β β βββ UserRepository.php # User CRUD operations
β β βββ SubmissionRepository.php # Submission CRUD operations
β βββ Services/ # Business logic layer
β β βββ AuthService.php # Auth business logic
β β βββ SubmissionService.php # Submission business logic
β βββ Validators/ # Input validation
β β βββ UserSignupValidator.php
β β βββ UserLoginValidator.php
β β βββ SubmissionValidator.php
β βββ Views/
β βββ dashboard.php
β βββ login.php
β βββ signup.php
β βββ reports.php
β βββ partials/
β βββ head.php
β βββ navbar.php
β βββ input.php
βββ config/ # Configuration files
β βββ app.php # App configuration
β βββ database.php # Database configuration
βββ public/ # Public web root
β βββ css/ # Stylesheets
β βββ js/ # JavaScript files
β βββ Images/ # Images
β βββ api/ # API endpoints
β βββ index.php # Entry point
β βββ signup.php # Signup page
β βββ login.php # Login page
β βββ dashboard.php # Dashboard page
β βββ submit.php # Form submission handler
β βββ logout.php # Logout handler
β βββ reports.php # Reports page
βββ vendor/ # Composer dependencies
βββ Instructions/ # Project documentation
βββ composer.json # Composer configuration
βββ database.sql # Database schema
βββ Dockerfile # PHP app container config
βββ docker-compose.yml # Multi-container orchestration
βββ README.md # This file
1. Clone the repository
git clone https://github.com/engrshishir/roxnor.git
cd roxnor2. Build and start containers
docker-compose up -d --buildThis command will:
- β Build the PHP 8.1 + Apache container
- β Pull MySQL 8.0 image
- β Pull phpMyAdmin image
- β Create isolated network
- β Initialize database with schema
- β Install Composer dependencies
3. Access the application
- Application: http://localhost:8080
- phpMyAdmin: http://localhost:8081
- Username:
roxnor_user - Password:
roxnor_password
- Username:
# View logs
docker-compose logs -f
# Stop containers
docker-compose down
# Restart containers
docker-compose restart
# Rebuild after code changes
docker-compose up -d --build
# Remove containers and volumes (fresh start)
docker-compose down -vβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PRESENTATION LAYER β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββββ β
β β HTML5 β β CSS3 β βJavaScriptβ β Views β β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββββ β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β CONTROLLER LAYER β
β ββββββββββββββββββββββ βββββββββββββββββββββββββββ β
β β AuthController β β SubmissionController β β
β β - signup() β β - create() β β
β β - login() β β - getFiltered() β β
β β - logout() β β - update() β β
β ββββββββββββββββββββββ βββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β VALIDATION LAYER β
β βββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β UserSignup β β UserLogin β β Submission β β
β β Validator β β Validator β β Validator β β
β βββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β SERVICE LAYER β
β ββββββββββββββββββββββ βββββββββββββββββββββββββββ β
β β AuthService β β SubmissionService β β
β β - Business Logic β β - Business Logic β β
β β - Orchestration β β - Orchestration β β
β ββββββββββββββββββββββ βββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β REPOSITORY LAYER β
β ββββββββββββββββββββββ βββββββββββββββββββββββββββ β
β β UserRepository β β SubmissionRepository β β
β β - CRUD Operations β β - CRUD Operations β β
β β - Data Mapping β β - Query Building β β
β ββββββββββββββββββββββ βββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β DATA LAYER β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Database (Singleton PDO) β β
β β - Connection Management β β
β β - Query Execution β β
β β - Transaction Handling β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β MySQL DATABASE β
β ββββββββββββββββββ ββββββββββββββββββββββ β
β β users table β β submissions table β β
β β - id β β - id β β
β β - name β β - receipt_id β β
β β - email βββββββββββββ - entry_by (FK) β β
β β - password β β - total_amount β β
β β - created_at β β - items (JSON) β β
β ββββββββββββββββββ ββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch
git checkout -b feature/YourFeature
- Commit your changes
git commit -m "Add: Your feature description" - Push to the branch
git push origin feature/YourFeature
- Open a Pull Request
- Follow PSR-1 and PSR-12 coding standards
- Write meaningful commit messages
- Add comments for complex logic
- Update documentation if needed
This project is licensed under the MIT License.
Image: engrshishir/roxnor-app
# Pull the latest image
docker pull engrshishir/roxnor-app:latest
# Or pull specific version
docker pull engrshishir/roxnor-app:1.0.0
# Clone repository for docker-compose.yml
git clone https://github.com/engrshishir/roxnor.git
cd roxnor
# Start all services (app, database, phpMyAdmin)
docker-compose up -d
# Access the application
# - App: http://localhost:8080
# - phpMyAdmin: http://localhost:8081Shishir - Roxnor Internship Assessment
This project is created for internship assessment purposes.