When a Laravel project starts small, putting logic in controllers and models is fine. But as more features arrive, it becomes difficult to understand what is happening where. I prefer to organize the project by domains and introduce a service layer.
A domain-driven folder structure
Instead of having everything in app/Models and app/Http/Controllers,
I like to introduce a Domain (or Modules) folder:
app/
Http/
Controllers/
Domain/
Users/
User.php
UserService.php
UserRepository.php
Orders/
Order.php
OrderService.php
OrderRepository.php
The goal is to keep everything related to a feature close together — model, service, repository, sometimes actions or DTOs.
Thin controllers, focused services
Controllers should just handle HTTP concerns: validation, authorization and sending responses. Business rules live in services:
class UserController extends Controller
{
public function store(UserService $service, UserStoreRequest $request)
{
$user = $service->createUser($request->validated());
return response()->json($user, 201);
}
}
This structure has made it easier for me to onboard new developers and keep the project maintainable after years of changes.