action-domain-responder
Web Presentation Patterns for PHP
This skill governs the web/HTTP layer — the thin edge that turns an HTTP request into a call on the application and turns the result into an HTTP response. Its central job is to keep that layer from leaking into the domain, and to correct a widespread misnomer.
The most important correction: "Web MVC" is not MVC
What PHP (and Rails, Spring, etc.) frameworks call "MVC" is not the original Model-View-Controller. It is Model 2 — Sun's server-side appropriation of the names, popularized by Apache Struts (Java) and Ruby on Rails, then copied by PHP frameworks. The original MVC (Smalltalk-80, 1979) was a client-side, in-memory GUI pattern: one MVC triad per screen element, connected by an observer graph that continuously notified views/controllers of state changes in memory. That has nothing to do with receiving one HTTP request and returning one HTTP response.
Worse, Model 2 prescribes putting business logic in the Controller — a UI component. That is the origin of the "fat controller" anti-pattern, and it directly contradicts the original MVC (where the model does the work). See web-mvc-is-not-mvc.md for the full distillation.
The better mental model: Action-Domain-Responder
Reframe the framework "controller" using Action-Domain-Responder (Paul M. Jones):
- Action — receives the HTTP request, invokes the domain, and builds (not renders) the response. HTTP glue only.
- Domain — "whatever does the domain work": the application/Service layer (orchestration, use cases) and the DDD domain layer beneath it (entities, policies, invariants). In ADR the Domain is the entry point into all of that, not just one layer.
- Responder — builds the entire HTTP response: status, headers, cookies, content-type, and body. A view/template is only one mechanism the Responder may use for the body; the Responder owns all response construction, not just rendering.
A framework "controller" is really an Action + Responder pair; the "model" is really the Domain plus the persistence behind it. Not every framework that claims MVC actually separates these — many controllers still mix request handling, domain calls, and response building. Use ADR as the placement rule, not a guarantee of the scaffold. See the caveat in web-mvc-is-not-mvc.md. For per-framework guidance on getting as close to proper ADR as each framework allows, see adr-by-framework.md. The classic patterns these build on — Page Controller, Front Controller, Template/Transform/Two Step View, Application Controller — are catalogued in classic-web-patterns.md as vocabulary for recognizing what the framework already gives you.