Project Structure
Complete directory tree with detailed explanations
Understanding DALT.PHP's directory structure helps you navigate both experiences:
- core framework experience (standalone core)
- guided learning experience (optional
.daltlayer)
Complete Directory Tree
DALT.PHP/
├── .dalt/ # Optional learning platform internals
│ ├── Http/
│ │ └── controllers/
│ │ ├── api/
│ │ │ └── verify.php # Verification API endpoint
│ │ └── learn/
│ │ ├── index.php # /learn homepage
│ │ ├── lesson.php # Lesson viewer
│ │ └── challenge.php # Challenge viewer
│ ├── resources/
│ │ ├── css/
│ │ │ └── input.css # Tailwind CSS source
│ │ ├── js/
│ │ │ ├── app.js # Vue app entry
│ │ │ └── components/ # Vue components
│ │ │ ├── LessonContent.vue
│ │ │ ├── ChallengeContent.vue
│ │ │ ├── ChallengeVerifier.vue
│ │ │ └── UnlockButton.vue
│ │ └── views/
│ │ ├── learn/ # Learning UI views
│ │ └── status/ # Error pages (403, 404, 500)
│ ├── routes/
│ │ └── routes.php # Platform routes
│ ├── stubs/
│ │ └── auth/ # Auth example template
│ ├── package.json # Node dependencies
│ ├── package-lock.json
│ └── vite.config.mjs # Vite configuration
│
├── app/ # User application (MVC structure)
│ └── Http/
│ └── controllers/
│ └── welcome.php # Default homepage controller
│
├── config/ # Configuration files
│ ├── app.php # App settings (name, env, debug)
│ └── database.php # Database connection config
│
├── .dalt/course/ # Learning content
│ ├── lessons/ # 6 comprehensive lessons
│ │ ├── 01-request-lifecycle/
│ │ │ └── README.md
│ │ ├── 02-routing/
│ │ │ └── README.md
│ │ ├── 03-middleware/
│ │ │ └── README.md
│ │ ├── 04-authentication/
│ │ │ └── README.md
│ │ ├── 05-database/
│ │ │ └── README.md
│ │ └── 06-sessions/
│ │ └── README.md
│ └── challenges/ # 5 debugging challenges
│ ├── broken-routing/
│ │ ├── README.md # Challenge description
│ │ ├── tests.php # Verification tests
│ │ ├── routes/
│ │ │ └── routes.php # Broken routes
│ │ └── Http/controllers/
│ │ └── posts/ # Challenge controllers (copied to app/Http/controllers/)
│ ├── broken-middleware/
│ ├── broken-auth/
│ ├── broken-database/
│ └── broken-session/
│
├── database/ # Database files
│ ├── app.sqlite # SQLite database file
│ └── migrations/ # SQL migration files
│ └── 001_create_users_table.sql
│
├── docs/ # Project documentation
│ ├── ARCHITECTURE_V2.md
│ ├── BEGINNER_EXPERIENCE_REPORT.md
│ ├── REFACTORING_SUMMARY.md
│ └── SQL_MIGRATION_RATIONALE.md
│
├── framework/ # Educational micro-framework
│ └── Core/ # Core framework classes
│ ├── Middleware/ # Middleware classes
│ │ ├── Auth.php # Authentication check
│ │ ├── Csrf.php # CSRF protection
│ │ ├── Guest.php # Guest-only routes
│ │ └── Middleware.php # Base middleware resolver
│ ├── App.php # Application container
│ ├── Authenticator.php # Auth helper
│ ├── bootstrap.php # Framework bootstrap
│ ├── ChallengeVerifier.php # Verification system
│ ├── Container.php # DI container
│ ├── Database.php # Database wrapper
│ ├── DatabaseManager.php # DB connection manager
│ ├── functions.php # Helper functions
│ ├── Migration.php # Migration runner
│ ├── Request.php # HTTP request wrapper
│ ├── Router.php # Routing system
│ ├── Session.php # Session management
│ ├── ValidationException.php # Validation errors
│ └── Validator.php # Input validation
│
├── public/ # Web root (document root)
│ ├── index.php # Application entry point
│ └── router.php # Dev server router script
│
├── resources/ # User resources
│ └── views/ # View templates
│ └── welcome.view.php # Default homepage view
│
├── routes/ # User routing
│ └── routes.php # Route definitions
│
├── storage/ # Runtime files
│ └── logs/ # Log files
│ ├── app.log # Application logs
│ └── challenges.log # Challenge completion logs
│
├── tests/ # Test suite
│ └── Unit/ # Unit tests
│
├── vendor/ # Composer dependencies
│
├── .env # Environment variables
├── .env.example # Environment template
├── .gitignore # Git ignore rules
├── artisan # CLI tool
├── composer.json # PHP dependencies
├── composer.lock # Locked PHP dependencies
├── package.json # Platform Node dependencies
├── README.md # Project README
└── TESTING_GUIDE.md # Testing instructionsDirectory Explanations
.dalt/ - Optional Platform Internals
Optional Layer: The .dalt/ directory powers guided lessons/challenges.
If removed, the framework core still runs.
Purpose: Provides the interactive learning experience without cluttering the user workspace.
Contains:
- Vue 3 frontend for
/learninterface - Verification API endpoints
- Platform routes and controllers
- Code templates (stubs)
- Vite build configuration
When to look inside:
- When working on platform features
- When contributing to learning workflows
app/ - User Application
Purpose: Your application code following MVC structure.
Contains:
Http/controllers/- Your controller files
Naming convention:
- Controllers:
posts/index.php,posts/show.php - Lowercase, descriptive names
- Organized in subdirectories by resource
Example:
app/Http/controllers/
├── welcome.php
├── posts/
│ ├── index.php
│ ├── show.php
│ ├── create.php
│ └── store.php
└── auth/
├── login.php
└── register.phpconfig/ - Configuration
Purpose: Application configuration files.
Files:
app.php- App name, environment, debug modedatabase.php- Database connection settings
Example (config/database.php):
return [
'database' => [
'driver' => 'sqlite',
'database' => base_path('database/app.sqlite')
]
];.dalt/course/ - Learning Content
Purpose: All educational material - lessons and challenges.
Structure:
lessons/- 6 markdown lessons explaining conceptschallenges/- 5 broken code challenges to fix
Lesson naming: 01-request-lifecycle/, 02-routing/, etc.
- Two-digit prefix for ordering
- Descriptive slug
- Contains
README.mdwith lesson content
Challenge structure:
broken-routing/
├── README.md # Challenge description, hints, solution
├── tests.php # Verification test definitions
├── routes/ # Broken route files
└── Http/controllers/ # Challenge-specific controllersdatabase/ - Database Files
Purpose: SQLite database and migration files.
Files:
app.sqlite- The actual database filemigrations/- SQL migration files
Migration naming: YYYYMMDDHHmmss_description.sql
- Timestamp prefix for ordering
- Descriptive name
.sqlextension (raw SQL, no PHP)
Example migration:
-- 20240315120000_create_posts_table.sql
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title VARCHAR(255) NOT NULL,
body TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);framework/ - Educational Framework
Purpose: The transparent micro-framework you learn from.
Core classes:
Router.php- URL matching and route registrationDatabase.php- PDO wrapper with prepared statementsSession.php- Session management and flash dataMiddleware/- Request filtering (Auth, CSRF, Guest)Container.php- Dependency injection containerMigration.php- SQL migration runner
Read the Source: The framework code is intentionally simple and well-commented. Reading it helps you understand how frameworks work!
public/ - Web Root
Purpose: The document root served by the web server.
Files:
index.php- Entry point for all requestsrouter.php- PHP dev server routing script
Why it's separate: Security best practice - only public/ is web-accessible, keeping sensitive files (config, framework) outside the web root.
resources/ - User Resources
Purpose: View templates and assets for your application.
Structure:
views/- PHP view templates
View naming: posts/index.view.php, auth/login.view.php
- Organized by resource
.view.phpextension for clarity
routes/ - User Routes
Purpose: Define URL-to-controller mappings.
File: routes.php - All your route definitions
Example:
<?php
global $router;
$router->get('/', 'welcome.php');
$router->get('/posts', 'posts/index.php');
$router->get('/posts/{id}', 'posts/show.php');
$router->post('/posts', 'posts/store.php')->only(['auth', 'csrf']);storage/ - Runtime Files
Purpose: Logs and runtime data.
Structure:
logs/app.log- Application logslogs/challenges.log- Challenge completion tracking
Permissions: Must be writable by web server.
tests/ - Test Suite
Purpose: Automated tests for the framework and application.
Structure:
Unit/- Unit tests- Uses Pest PHP testing framework
File Naming Conventions
Controllers
- Lowercase:
posts/index.php, notPosts/Index.php - Descriptive:
posts/store.php, notposts/save.php - RESTful:
index,show,create,store,edit,update,destroy
Views
- Match controller:
posts/index.view.phpforposts/index.php .view.phpextension for clarity- Organized in subdirectories
Migrations
- Timestamp prefix:
20240315120000_create_posts_table.sql - Descriptive name:
create_posts_table, notmigration1 .sqlextension (raw SQL)
Lessons
- Two-digit prefix:
01-,02-, etc. - Descriptive slug:
request-lifecycle,routing - Contains
README.md
Challenges
- Prefix with
broken-:broken-routing,broken-auth - Descriptive of the bug:
broken-middleware, notchallenge-3 - Contains
README.mdandtests.php
Hidden Files and Directories
.dalt/
Hidden platform code. Beginners don't need to see it.
.env
Environment variables (database credentials, debug mode). Never commit to Git.
.gitignore
Specifies files Git should ignore (vendor/, node_modules/, .env).
vendor/
Composer dependencies. Generated, not committed.
node_modules/
Node dependencies (in .dalt/). Generated, not committed.
Where to Put Your Code
| File Type | Location | Example |
|---|---|---|
| Controllers | app/Http/controllers/ | posts/index.php |
| Views | resources/views/ | posts/index.view.php |
| Routes | routes/routes.php | $router->get('/posts', ...) |
| Migrations | database/migrations/ | 20240315_create_posts.sql |
| Config | config/ | app.php, database.php |
What NOT to Edit
| Directory | Why | Exception |
|---|---|---|
.dalt/ | Optional platform code | Only when working on platform features |
framework/ | Framework code | Only for challenges |
vendor/ | Composer dependencies | Never |
public/index.php | Entry point | Rarely needed |
Next Steps
- Architecture Overview - Understand the three-layer design
- Framework Internals - Deep dive into core classes
- Building a Blog - Put the structure to use