Learn when to extract business logic and which pattern to use
As applications grow, controllers become bloated with business logic. The solution is to extract this logic into dedicated classes.
All logic in controller (65+ lines per method)
Group related operations (UserService with 4 methods)
Single responsibility (CreateUserAction, one job)
Click each button to see the same user registration implemented in different ways
Processing registration...
ID:
Name:
Email:
ID:
Name:
Owner:
ID:
Name:
| Metric | Bloated Controller | Service Class | Action Classes |
|---|---|---|---|
| Lines of Code | |||
| Files Count | |||
| Testability | |||
| Maintainability | |||
| Reusability | |||
| Complexity | |||
| Overall Rating |
class UserController extends Controller {
public function store(Request $request) {
// 65+ lines of validation, user creation,
// company setup, team management,
// email sending, API calls, etc.
// All in one massive method!
}
}
class UserService {
public function createUser(array $data) { /* ... */ }
public function sendWelcomeEmail(User $user) { /* ... */ }
public function updateProfile(User $user, array $data) { /* ... */ }
public function deleteAccount(User $user) { /* ... */ }
}
class UserController extends Controller {
public function store(Request $request, UserService $userService) {
$user = $userService->createUser($request->validated());
$userService->sendWelcomeEmail($user);
return response()->json($user);
}
}
// CreateUserAction.php
class CreateUserAction {
public function execute(array $data): User {
// Only user creation logic
}
}
// SendWelcomeEmailAction.php
class SendWelcomeEmailAction {
public function execute(User $user): void {
// Only email sending logic
}
}
// Controller
class UserController extends Controller {
public function store(
Request $request,
CreateUserAction $createUser,
SendWelcomeEmailAction $sendEmail
) {
$user = $createUser->execute($request->validated());
$sendEmail->execute($user);
return response()->json($user);
}
}
Only for:
Good for:
Best for: