Architecture decides where a responsibility belongs and which direction dependencies point. A useful small PHP application keeps request parsing in the HTTP layer, business decisions in services or domain objects, and SQL behind focused persistence code.
After this lesson, you can trace a request through a front controller, distinguish controller, service, and repository responsibilities, inject a dependency through a constructor, and avoid turning MVC names into unnecessary layers.
Keep public/index.php small. It coordinates bootstrapping and dispatch rather than containing validation, SQL, and page HTML for every feature.
| Layer | Owns | Avoid |
|---|---|---|
| HTTP | Methods, input mapping, status, headers | Business rules and raw SQL |
| Application | Use-case coordination and transaction boundary | HTML and superglobals |
| Domain | State, invariants, decisions | Framework and database details |
| Persistence | Queries and record mapping | Authorization and redirects |
Pass required collaborators into the constructor. This makes dependencies visible, prevents hidden global state, and lets tests replace infrastructure with a focused fake.
<?php
interface TaskRepository
{
public function save(string $title): int;
}
final class CreateTask
{
public function __construct(private TaskRepository $tasks) {}
public function handle(string $title): int
{
$title = trim($title);
if ($title === '') {
throw new InvalidArgumentException('Task title is required.');
}
return $this->tasks->save($title);
}
}
The use case knows the capability it needs but not whether PDO, memory, or another adapter implements it.
Create concrete dependencies in one bootstrap location and pass them inward. A dependency-injection container may automate this later, but it should not become a service locator called throughout domain code.
<?php
$pdo = new PDO($dsn, $user, $password, $options);
$tasks = new PdoTaskRepository($pdo);
$createTask = new CreateTask($tasks);
PdoTaskRepository and connection values belong at the application edge; CreateTask remains independent of PDO.
0 of 2 checked
Try this next
0 of 2 completed
Explore 500+ free tutorials across 20+ languages and frameworks.