Appearance
Controller
Prefer Single Action Controllers
One of the main goals of classes in OOPs is to encapsulate data and behavior. For controllers, there is usually nothing to encapsulate and reuses between actions (public methods); for this reason, we prefer to have one action per controller.
php
final class ShowMemberProfileController
{
public function __invoke(Request $request)
{
// ...
}
}No Parent class
There are usually no reasons of doing this when you follow other rules from these conventions.
Invokable controller naming conventions
There are no hard rules in naming controllers, so always think about what is the responsibility of the controller and try to make the name descriptive. A good rule to follow is to start the name with a verb. Below you can find some examples that can be treated as a baseline when naming invokable controllers.
Common operations:
- Index:
ListResourcesController - Create:
CreateResourceController - Store:
StoreResourceController - Show:
ShowResourceController - Edit:
EditResourceController - Update:
UpdateResourceController - Destroy:
DeleteResourceController
Other examples:
- Merge:
MergeResourcesController - Process:
ProcessResourceController
Controllers Should Not Extend/Inherit
Controllers SHOULD NOT extend any base class: there are usually no reasons to do it. Prefer composition (using DI) instead of inheritance. Also, often common logic can be extracted into Middleware.
Singular resource name
Controllers that control a resource must use the singular resource name.
diff
-final class CoursesController
+final class CourseControllerStick to default CRUD action names
Stick to default CRUD action names when possible: index, create, store, show, edit, update, and destroy.
This is a loose guideline that doesn’t need to be enforced.
Inject route params, then Request, then other dependencies
Order of controller action parameters:
- Route params or bound Models
- Request instance
- Other dependencies
php
public function __invoke(User $user, Request $request, DetachUserFromTeamAction $detachAction)
{
...
}The same for scalar GET params (good example: public function __invoke(int $teamId, Request $request).
Use Action classes
Actions are classes that take care of one specific task. Controller classes have access to the application context (Request, Cache, Session, etc.), extract the data from the context, validate it and pass to the Action class.
php
final class DetachTeamMemberController
{
public function __invoke(Team $team, Member $member, DetachTeamMemberAction $detachAction): RedirectResponse
{
$this->authorize('update', $team);
$detachAction->execute($team, $member);
return redirect()->route('teams.show', [$team]);
}
}