laravel-controllers

Installation
SKILL.md

Laravel Controllers

A controller is the HTTP edge of one operation. It takes the validated request and the bound models, builds the DTO, calls one action and returns a response. It holds no business rules, no writes and no authorization, so the same operation can run from a job or a command, and the controller stays a few lines long. A listing is a query class; a response is an API resource that maps every field by hand. Everything here is JSON.

Rules

  • Gather, call one action, respond. No writes, no business rules, no branching on domain state. Even a lone $order->update(...) belongs in an action (laravel-actions).
  • Resource methods on a singular {Model}Controller. OrderController holds index, show, store, update and destroy, nothing else. A nested resource is {Parent}{Child}Controller (OrderLineController).
  • Any other operation is an invokable controller. A state transition or command is {Verb}{Model}Controller with __invoke() (CancelOrderController); a read-only view that isn't show is {Model}{Noun}Controller (OrderHistoryController). A custom method on a resource controller hides an operation among five others.
  • No return types on controller methods. The body says what comes back (a resource, a collection, a helper response) and the feature test pins the status and shape; a declared type adds nothing. This is the one exception to laravel-quality's return-type rule.
  • Inject the action into the method, named after its class. CancelOrderAction $cancelOrderAction, never $action. Parameters run form request, bound models, then the action.
  • Build the DTO with the surface's transformer. CreateOrderDataTransformer::fromRequest($request) goes straight into the action. A request array never leaves the controller (laravel-dtos).
  • The acting user is user(), passed in. When the operation depends on who's acting, the controller passes user() to the action (laravel-providers defines the helper).
  • No authorization in the controller. The route carries ->can() (laravel-routing owns that rule). Never $this->authorize() or a Gate check; the base controller doesn't use AuthorizesRequests, so the call doesn't exist.
  • Validation is the form request's. Type-hint it; never $request->validate() in the method (laravel-validation).
  • A read with no rules needs no action. show returns the bound model's resource, loading what it renders with loadMissing(). index is a query class. A read that computes, caches or calls a service is a Get…Action.
  • Extend the app's base controller. App\Http\Controllers\Controller uses the response helpers trait and nothing else.

Example

Installs
57
GitHub Stars
15
First Seen
Mar 27, 2026