A 100% self-written PHP framework demonstrating advanced software architecture principles, design patterns, and modern PHP development practices. This project showcases a complete web application framework built from the ground up, featuring a robust dependency injection system, event-driven architecture, middleware support, and comprehensive tooling.
This project was initiated as a comprehensive training and supervision tool for apprentices and junior developers, designed to ensure strong talent development through hands-on exposure to enterprise-level software architecture.
- Design Pattern Mastery: Comprehensive implementation of 13 major design patterns
- Modern PHP Practices: Strict typing, attributes, readonly classes, and advanced language features
- Software Architecture: Layered architecture with clear separation of concerns
- Code Quality Standards: Static analysis, type checking, and architecture enforcement
- Best Practices: Security, performance optimization, and maintainability
- Comprehensive Documentation: Detailed README serves as learning material
- Clear Architecture: Well-structured codebase for easy navigation and understanding
- Extensible Design: Framework encourages experimentation and feature additions
- Quality Assurance: Built-in tools for teaching code quality standards
This framework implements a layered architecture with clear separation of concerns, following SOLID principles and modern design patterns. The architecture is built around several core components:
- Application Layer: Central orchestrator managing the request lifecycle
- Factory Management: Advanced dependency injection with attribute-based configuration
- HTTP Layer: Request/Response handling with middleware support
- Event System: Observable pattern implementation with lifecycle events
- Routing: Attribute-based routing with constraint support
- View System: Template engine with view helpers
- Validation: Chain-based validation system
- Queue System: Database-backed job queuing
- Console: Command-line interface with attribute-based commands
The framework features a sophisticated dependency injection container with:
- Attribute-based configuration using PHP 8 attributes
- Autowiring with dependency resolution
- Factory registration with custom factory classes
- Instance locking to prevent flushing of critical instances across requests
- Memory management with automatic flushing
- Flyweight pattern for instance caching and memory optimization
#[InstanceLocked]
#[ProducedBy(RouterFactory::class)]
final class Router implements RouterInterface
{
// Implementation with automatic dependency injection
// InstanceLocked prevents this instance from being flushed between requests
}
// Flyweight pattern: Global instance access with caching
$router = instance(RouterInterface::class); // Returns cached instanceComprehensive event system implementing the Observer pattern with multiple event types and priority-based handling:
Base Event Class
abstract readonly class Event implements ObservableInterface
{
use CanOccur; // Provides static occur() method
}Event Occurrence
// Static method for firing events
ApplicationBootStarted::occur();
RequestCreated::occur($request);
ResponseSent::occur($response);Automatic events fired during application lifecycle:
- ApplicationBootStarted: Fired when application boot begins
- ApplicationBooted: Fired when application boot completes
- RequestCreated: Fired when a new request is created
- RouterCreated: Fired when router is instantiated
- RouterMatched: Fired when route matching completes
- ResponseCreated: Fired when response is created
- ResponseSent: Fired when response is sent
- RunFinished: Fired when request handling completes
- WorkerHandlerStarted/Finished: Fired for worker lifecycle
Domain-specific events for business logic:
final readonly class Registered extends Event
{
public function __construct(
public string $email,
public string $firstName,
public string $lastName,
) {}
}Events can be queued for asynchronous processing using the CanQueueObservables trait:
// Event that can be queued and processed asynchronously
final readonly class EmailNotificationEvent extends Event implements QueueableInterface
{
use CanQueueObservables;
public function __construct(
public string $recipient,
public string $subject,
public string $content
) {}
public function getQueuePriority(): QueuePriority
{
return QueuePriority::High; // High priority = processed first
}
public function execute(): void
{
// This method is called when the event is processed from the queue
// It automatically fires the event using self::occur($this)
}
}
// Queue the event for asynchronous processing
EmailNotificationEvent::queue($recipient, $subject, $content);Observers register event handlers with priority support:
final class RegisteredEmailListener implements ObserverInterface
{
public function observe(EventAttacherInterface $attacher): void
{
$attacher->attach(
Registered::class,
fn(Registered $event) => $this->sendWelcomeEmailToUser($event)
);
$attacher->attach(
Registered::class,
fn(Registered $event) => $this->sendNewUserEmailToAdmin($event)
);
}
}Events can be handled with different priorities:
$attacher->attach(
LifecycleEventInterface::class,
function (Event $event): void {
$this->occurredTimes[$event::class] = microtime(true);
},
-1
);Event Handler Priority System:
- Numbers: The larger the number, the higher the priority
- Zero: Default priority
- Type-safe events with strict typing
- Priority-based handling for event ordering
- Multiple observers per event type
- Interface-based observables for flexibility
- Automatic event registration through observers
- Queueable events for asynchronous processing with
CanQueueObservables - Lifecycle monitoring with benchmark capabilities
- Dual priority systems: Event handler priority and queue processing priority
Modern routing system using PHP 8 attributes:
#[Route(
route: '/auth/login',
httpMethod: HttpMethod::POST,
middlewareClasses: [CsrfTokenMiddleware::class]
)]
final readonly class LoginSubmitController implements ControllerInterface
{
#[Request(LoginRequest::class)]
public function handle(RequestInterface $request): ResponseInterface
{
// Controller logic
}
}Flexible middleware implementation with chain-of-responsibility pattern:
- Automatic middleware chaining
- Priority-based execution
- Route-specific middleware
- Global middleware support
Comprehensive validation framework with multiple layers of validation:
Requests can be validated using the ValidatableRequest base class:
final readonly class LoginRequest extends ValidatableRequest
{
protected function validatorClass(): string
{
return LoginValidator::class;
}
public function email(): string
{
return (string) $this->getPayload()->get('email');
}
public function password(): string
{
return (string) $this->getPayload()->get('password');
}
}Chain-based validation with multiple validator types:
final readonly class LoginValidator extends MapValidator
{
public function __construct(
EmailValidator $emailValidator,
FilledValidator $notEmptyValidator,
) {
parent::__construct([
'email' => new ValidatorChain([
$notEmptyValidator,
$emailValidator,
]),
'password' => $notEmptyValidator,
]);
}
}Automatic validation with flash message integration:
#[Request(LoginRequest::class)]
public function handle(RequestInterface $request): ResponseInterface
{
if (!$this->valid($request)) {
return new RedirectResponse('/login');
}
// Process validated request
return $this->login($request);
}- FilledValidator: Ensures non-empty string values
- EmailValidator: Validates email format
- ExistsValidator: Checks database existence
- ListValidator: Validates array lists
- MapValidator: Validates associative arrays
- ValidatorChain: Combines multiple validators
- Type-safe validation with strict typing
- Custom error messages with field name substitution
- Flash message integration for user feedback
- Extensible validator system for custom rules
- Automatic validation in controllers
Advanced job queuing system with multiple backend support:
The framework provides an extensible queue system through the QueueInterface:
interface QueueInterface
{
public function append(QueueableInterface $queueable): void;
public function pop(): ?QueueableInterface;
}- DatabaseQueue: Persistent database-backed queuing (currently implemented)
- Extensible Factory: Easy addition of custom queue backends
Jobs support priority levels for processing order:
enum QueuePriority: int
{
case Low = 0;
case Medium = 1;
case High = 2;
}Jobs extend the base Job class with automatic queuing support:
final readonly class EmailJob extends Job
{
public function __construct(
public string $email,
public string $subject,
public string $content
) {}
public function getQueuePriority(): QueuePriority
{
return QueuePriority::Low;
}
public function execute(EmailManager $emailManager): void
{
$emailManager->send($this->email, $this->subject, $this->content);
}
}Static queuing method for convenient job dispatch:
EmailJob::queue($email, $subject, $content);The factory-based architecture allows easy addition of custom queue systems. The following could be implemented by extending QueueInterface:
- Redis Queue: For high-performance in-memory queuing (not implemented)
- RabbitMQ Queue: For distributed message processing (not implemented)
- SQS Queue: For cloud-based queuing (not implemented)
- Custom Queue: Any queue system implementing
QueueInterface
- Priority-based processing with configurable priorities
- Automatic dependency injection for job execution
- Command pattern implementation
- Factory-based instantiation for easy backend switching
- Type-safe job handling with strict typing
- Extensible architecture for custom queue implementations
- Queueable events with
CanQueueObservablestrait - Asynchronous event processing for performance optimization
Attribute-based command-line interface:
#[Command('dequeue')]
final readonly class DequeueCommand implements CommandInterface
{
public function run(array $arguments, ConsoleOutputInterface $output): void
{
// Command implementation
}
}The framework supports multiple application workers for different deployment scenarios:
- Default Worker: Traditional request-per-process handling
- FrankenPHP Worker: High-performance Go-based PHP server integration
- Extensible Architecture: Easy addition of custom workers
// Using FrankenPHP worker for high-performance deployment
$application = new Application(
new FactoryManager(),
[AppBootstrapper::class],
[CsrfTokenMiddleware::class],
FrankenPHPWorker::class
);
// FrankenPHP deployment with Docker
docker run --rm \
-e FRANKENPHP_CONFIG="worker /app/public/index.php" \
-v $PWD:/app \
-p 80:80 -p 443:443 -p 443:443/udp \
dunglas/frankenphpThe FrankenPHP worker provides:
- Request recycling for improved performance
- Memory management with automatic flushing
- Lifecycle events for worker monitoring
- Configurable request limits via
MAX_REQUESTSenvironment variable
- PHP 8.3+ with strict typing and modern features
- PDO for database operations
- Flow PHP Array Dot for configuration management
- Vlucas PHP Dotenv for environment configuration
- PHPStan (Level 9) for static analysis
- Psalm for type checking
- Deptrac for architecture enforcement
- PHP CS Fixer for code style
- Rector for code migration
- Whoops for error handling
- Symfony Var Dumper for debugging
app/
โโโ framework/ # Core framework implementation
โ โโโ src/
โ โ โโโ Application/ # Application lifecycle management
โ โ โโโ Bootstrappers/ # Bootstrapping system
โ โ โโโ Configurations/ # Configuration management
โ โ โโโ Consoles/ # CLI command system
โ โ โโโ Databases/ # Database abstraction
โ โ โโโ Dependencies/ # Dependency resolution
โ โ โโโ Emails/ # Email handling
โ โ โโโ Events/ # Event system
โ โ โโโ Factories/ # Factory pattern implementation
โ โ โโโ FactoryManagers/ # Dependency injection container
โ โ โโโ Http/ # HTTP layer (requests, responses, routing)
โ โ โโโ Jobs/ # Job queuing system
โ โ โโโ Listeners/ # Event listeners
โ โ โโโ Models/ # Model interfaces
โ โ โโโ Providers/ # Service providers
โ โ โโโ Queues/ # Queue implementations
โ โ โโโ Sessions/ # Session management
โ โ โโโ Validations/ # Validation framework
โ โ โโโ Views/ # View system
โโโ src/ # Application code
โ โโโ Bootstrappers/ # Application bootstrappers
โ โโโ Events/ # Application events
โ โโโ Http/ # Controllers, requests, validators
โ โโโ Listeners/ # Event listeners
โ โโโ Models/ # Domain models
โ โโโ Services/ # Business logic services
โ โโโ Validators/ # Custom validators
โโโ config/ # Configuration files
โโโ views/ # Template files
โโโ public/ # Web entry point
The framework uses a flexible configuration system:
// config/database.php
return [
'database' => [
'dsn' => env('DATABASE_DSN', 'sqlite::memory:'),
'username' => env('DATABASE_USERNAME'),
'password' => env('DATABASE_PASSWORD'),
]
];- PHP 8.3 or higher
- Composer
- SQLite (or other PDO-compatible database)
-
Clone the repository
git clone <repository-url> cd app
-
Install dependencies
composer install
-
Configure environment
cp .env.example .env # Edit .env with your configuration -
Run the application
php -S localhost:8000 -t public
# Code style
composer codestyle-fix
composer codestyle-check
# Static analysis
vendor/bin/phpstan analyse
vendor/bin/psalm
# Architecture analysis
vendor/bin/deptrac- Custom DI container with attribute-based configuration
- Autowiring with dependency resolution
- Factory pattern integration
- Event system with observable interfaces
- Priority-based event handling with negative numbers for higher priority
- Lifecycle event management with automatic firing
- Custom application events with queueable support
- Multiple observers per event type
- Middleware chain implementation
- Validation chain system with multiple validator types
- Request processing pipeline
- Field-level validation with MapValidator
- Factory manager with custom factories
- Attribute-based factory registration
- Instance management with request-scoped flushing
- Instance locking for persistent instances across requests
- Console command system
- Job queuing implementation
- Request handler abstraction
- Abstract base classes with defined algorithms
Eventbase class withCanOccurtraitJobbase class withCanQueuetraitMiddlewarebase class with chain handling
- Application worker selection
- Multiple deployment strategies
- Runtime worker configuration
- Instance caching through FactoryManager
- Shared object instances via
instance()function - Memory optimization for expensive objects
- Global instance access with type safety
- Request decoration with
DecoratedRequestbase class ValidatableRequestextendsDecoratedRequestfor validation- Request interface enhancement without modification
- Composition-based request enhancement
- Extensive use of
final readonlyclasses - Immutable data structures throughout the framework
- Type-safe value objects with strict typing
- Enum-based value objects (
QueuePriority,HttpMethod)
- Service providers for framework components
RouteProvider,ObserverProvider,CommandProvider- Centralized registration of framework services
- Extensible provider system for custom components
- Application construction with configurable components
- Step-by-step bootstrapping process
- Framework and application bootstrapper separation
- Fluent interface for application configuration
- CSRF Protection with token validation
- Authentication Middleware for route protection
- Advanced Input Validation with multi-layer validation system
- Type-Safe Request Handling with strict validation
- Session Management with flash messages
- Request Decoration for enhanced security
- Field-Level Validation with custom error messages
The project maintains high code quality standards:
- PHPStan Level 9 static analysis
- Psalm type checking with strict configuration
- Deptrac architecture enforcement
- PHP CS Fixer code style compliance
- Comprehensive test coverage (framework design supports testing)
Complete event-driven architecture with multiple event types:
- Lifecycle Events: Automatic application lifecycle monitoring
- Custom Events: Domain-specific business logic events
- Queueable Events: Asynchronous event processing with
CanQueueObservables - Priority-Based Handling: Event ordering with dual priority systems
- Benchmark Events: Performance monitoring capabilities
- Observer Registration: Automatic event listener registration
- Asynchronous Processing: Events can be queued for background processing
Sophisticated application construction with step-by-step bootstrapping:
- Framework Bootstrapper: Core framework component registration
- Application Bootstrapper: Application-specific configuration
- Finalize Bootstrapper: Service provider registration and finalization
- Configurable Components: Factory manager, middleware, workers
- Fluent Interface:
$application->boot()->run()chaining
Flexible deployment architecture supporting multiple application workers:
// Traditional deployment with default worker
$application = new Application(
new FactoryManager(),
[AppBootstrapper::class],
[CsrfTokenMiddleware::class]
);
// High-performance FrankenPHP deployment
$application = new Application(
new FactoryManager(),
[AppBootstrapper::class],
[CsrfTokenMiddleware::class],
FrankenPHPWorker::class
);
$application->boot()->run();Note: The InstanceLocked attribute is crucial for e.g. FrankenPHP workers to prevent critical instances (like Router, ViewGenerator) from being flushed between requests, ensuring optimal performance.
Complete application lifecycle with event-driven bootstrapping and worker-specific events:
Template engine with view helpers and data injection:
$viewGenerator->generate('home', ['user' => $user]);PDO-based database manager with model support:
$databaseManager->save($user);
$users = $databaseManager->select(User::class);Extensible job queuing with multiple backend support:
// Easy job queuing with static method
EmailJob::queue($email, $subject, $content);
// Custom queue backend support
$jobManager->queue(new EmailJob($user));The framework includes a complete web application demonstrating:
- User Authentication (login/register/logout)
- Form Validation with custom validators
- Flash Messages for user feedback
- Responsive Design with modern UI
- Security Features (CSRF, authentication)
The framework architecture supports easy extension:
- Caching Layer with multiple backends
- API Support with JSON responses
- Database Migrations system
- Testing Framework integration
- Plugin System for modular extensions
- Additional Queue Backends (Redis, RabbitMQ, SQS) - easily implementable via
QueueInterface - Queue Monitoring and management tools
- Lazy Loading of dependencies
- Memory Management with automatic flushing between requests
- Instance Locking for persistent instances across requests (critical for FrankenPHP)
- Flyweight Pattern for instance caching and memory optimization
- Efficient Routing with constraint-based matching
- Optimized Event Handling with priority sorting
- Multi-Worker Support for different deployment scenarios
- Request Recycling with FrankenPHP for improved performance
- Configurable Request Limits via
MAX_REQUESTSenvironment variable for worker recycling
This project demonstrates advanced PHP framework development skills including:
- Modern PHP 8 Features (attributes, readonly classes, union types)
- SOLID Principles implementation
- Design Patterns mastery
- Architecture Design expertise
- Code Quality standards
- Security Best Practices
This framework serves as an excellent mentorship tool for:
- Apprentices: Learning enterprise-level software development
- Junior Developers: Understanding advanced architectural concepts
- Code Review Training: Comprehensive codebase for review practice
- Architecture Discussions: Real-world examples of design decisions
- Best Practices: Industry-standard development practices and tooling
The project's complexity and comprehensive documentation make it ideal for hands-on learning and mentorship programs.
This project is a showcase of custom framework development skills and architectural expertise.
Built with โค๏ธ using modern PHP practices and advanced software architecture principles.