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.OrderControllerholdsindex,show,store,updateanddestroy, 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}Controllerwith__invoke()(CancelOrderController); a read-only view that isn'tshowis{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 passesuser()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 aGatecheck; the base controller doesn't useAuthorizesRequests, 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.
showreturns the bound model's resource, loading what it renders withloadMissing().indexis a query class. A read that computes, caches or calls a service is aGet…Action. - Extend the app's base controller.
App\Http\Controllers\Controlleruses the response helpers trait and nothing else.