Architecture Overview
Deep dive into DALT.PHP system design and components
DALT.PHP is built with a clear separation between platform code, framework code, and user code. This architecture keeps beginners focused on learning while providing transparency into how everything works.
Three-Layer Architecture
┌─────────────────────────────────────────────────────────┐
│ Platform Layer │
│ (.dalt/ directory - Learning UI, Verification System) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Framework Layer │
│ (framework/ directory - Router, Database, Session) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ User Layer │
│ (app/, routes/, course/ - Your code & challenges) │
└─────────────────────────────────────────────────────────┘1. Platform Layer (.dalt/)
The platform layer provides the learning experience - the interactive UI, verification system, and development tools. It's hidden in the .dalt/ directory to reduce cognitive load.
What's inside:
- Learning UI controllers (
/learnroutes) - Vue 3 components for interactive interface
- Verification API endpoints
- Code templates and stubs
- Vite configuration for frontend builds
Why it's hidden: Beginners don't need to understand Vue, Vite, or the verification system to learn backend concepts. The platform "just works" in the background.
2. Framework Layer (framework/)
The framework layer is the educational micro-framework - intentionally simple and transparent. Unlike production frameworks, every line of code is meant to be read and understood.
Core components:
Router.php- URL-to-controller mappingDatabase.php- PDO wrapper with prepared statementsSession.php- Session managementMiddleware/- Request filtering (Auth, CSRF, Guest)Container.php- Dependency injectionMigration.php- Raw SQL migration runner
Why it's transparent: You learn by reading the framework source code. No magic, no hidden abstractions.
3. User Layer (app/, routes/, course/)
The user layer is where you write code and complete challenges. This is your workspace.
What you work with:
app/Http/controllers/- Your controllersroutes/routes.php- Your route definitionscourse/lessons/- Lesson content to readcourse/challenges/- Broken code to fix
Request Lifecycle
Here's how a request flows through DALT.PHP:
1. Browser Request
↓
2. public/index.php (Entry point)
↓
3. framework/Core/bootstrap.php (Load dependencies)
↓
4. Router::route() (Match URL to controller)
↓
5. Middleware Pipeline (Auth, CSRF, etc.)
↓
6. Controller Execution (Your code or platform code)
↓
7. View Rendering (PHP templates)
↓
8. Response to BrowserDetailed Flow
Step 1-3: Bootstrap
// public/index.php
require __DIR__ . '/../framework/Core/bootstrap.php';
// bootstrap.php loads:
// - Composer autoloader
// - Environment variables (.env)
// - Helper functions
// - Database connection
// - Session startStep 4: Routing
// Router matches URL to controller
$router->get('/posts/{id}', 'posts/show.php');
// Extracts parameters: ['id' => '123']
// Resolves controller path: app/Http/controllers/posts/show.phpStep 5: Middleware
// Middleware runs before controller
$router->get('/dashboard', 'dashboard.php')->only('auth');
// Auth middleware checks $_SESSION['user']
// If not logged in, redirects to /Step 6-7: Controller & View
// Controller (app/Http/controllers/posts/show.php)
$post = $db->query('SELECT * FROM posts WHERE id = ?', [$id])->find();
view('posts/show.view.php', ['post' => $post]);
// View renders HTML with dataPlatform vs Framework vs User Code
Understanding what code belongs where is crucial:
| Layer | Purpose | Examples | Should You Edit? |
|---|---|---|---|
| Platform (.dalt/) | Learning experience | Vue components, verification API | ❌ No |
| Framework (framework/) | Core functionality | Router, Database, Session | ⚠️ Only for challenges |
| User (app/, routes/) | Your application | Controllers, routes | ✅ Yes |
Challenge Exception: Some challenges require editing framework files (e.g., fixing Authenticator.php). This is intentional - you're debugging the framework itself!
Directory Structure
DALT.PHP/
├── .dalt/ # Platform internals (hidden)
│ ├── Http/controllers/ # Learning UI controllers
│ │ ├── learn/ # /learn routes
│ │ └── api/ # /api/verify endpoint
│ ├── resources/
│ │ ├── js/components/ # Vue 3 components
│ │ ├── css/ # Tailwind CSS
│ │ └── views/ # Platform views
│ ├── routes/ # Platform routes
│ ├── stubs/ # Code templates
│ ├── package.json # Node dependencies
│ └── vite.config.mjs # Vite configuration
│
├── app/ # User application
│ └── Http/controllers/ # Your controllers
│
├── course/ # Learning content
│ ├── lessons/ # 6 lessons (markdown)
│ └── challenges/ # 5 challenges (broken code)
│
├── framework/ # Educational framework
│ └── Core/ # Core classes
│ ├── Router.php # Routing system
│ ├── Database.php # Database wrapper
│ ├── Session.php # Session management
│ ├── Middleware/ # Middleware classes
│ ├── Container.php # DI container
│ └── Migration.php # Migration runner
│
├── config/ # Configuration
│ ├── app.php # App settings
│ └── database.php # Database config
│
├── database/ # Database files
│ ├── app.sqlite # SQLite database
│ └── migrations/ # SQL migration files
│
├── public/ # Web root
│ ├── index.php # Entry point
│ └── router.php # Dev server router
│
├── resources/ # User resources
│ └── views/ # Your view templates
│
├── routes/ # User routes
│ └── routes.php # Route definitions
│
├── storage/ # Runtime files
│ └── logs/ # Application logs
│
└── tests/ # Test suiteComponent Relationships
Router → Middleware → Controller
// routes/routes.php
$router->get('/dashboard', 'dashboard.php')->only('auth');
// Flow:
// 1. Router matches /dashboard
// 2. Middleware 'auth' runs (checks session)
// 3. If auth passes, controller executes
// 4. If auth fails, redirects to /Database → Models (Implicit)
DALT.PHP doesn't have explicit models. You query directly:
// In controller
$posts = $db->query('SELECT * FROM posts')->get();This is intentional - you learn SQL, not ORM abstractions.
Container → Dependency Injection
// Framework uses container for DI
$db = App::resolve(Database::class);
$router = App::resolve(Router::class);
// You can use it too
App::bind('MyService', function() {
return new MyService();
});
$service = App::resolve('MyService');Platform Routes vs User Routes
DALT.PHP has two routing systems:
Platform Routes (.dalt/routes/)
Handle learning UI and verification:
/learn- Browse lessons and challenges/learn/lessons/{slug}- View lesson/learn/challenges/{slug}- View challenge/api/verify/{challenge}- Run verification
These routes are registered automatically and don't appear in your routes/routes.php.
User Routes (routes/routes.php)
Your application routes:
$router->get('/', 'welcome.php');
$router->get('/posts', 'posts/index.php');
$router->get('/posts/{id}', 'posts/show.php');Why This Architecture?
1. Separation of Concerns
- Platform code doesn't interfere with learning
- Framework code is readable and educational
- User code is clean and focused
2. Progressive Disclosure
- Beginners see only what they need
- Advanced learners can explore
.dalt/if curious - Framework source is always available to read
3. Real-World Patterns
- MVC structure (app/Http/controllers/)
- Configuration files (config/)
- Migration system (database/migrations/)
- Middleware pipeline (framework/Core/Middleware/)
4. Debugging-Friendly
- Clear error messages
- Readable stack traces
- No magic methods or hidden behavior
- Framework source is transparent
Next Steps
- Framework Internals - Deep dive into Router, Database, etc.
- Project Structure - Detailed directory explanations