Project Structure
Complete directory tree with detailed explanations
Understanding DALT.PHP's directory structure helps you navigate the codebase and know where to find (or place) different types of files.
Complete Directory Tree
DALT.PHP/
├── .dalt/ # Platform internals (hidden from beginners)
│ ├── 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
│
├── 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
│ ├── 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/ - Platform Internals
Hidden by Design: The .dalt/ directory is prefixed with a dot to hide it from beginners. It contains the learning platform code that "just works" in the background.
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:
- Never, unless you're curious about how the platform works
- Or contributing to the platform itself
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')
]
];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/ | Platform code | Never (unless contributing) |
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