Originally published on laravel.learnio.dev — part of the Laravel best practices course. View this lesson on the original site.
In this lesson
Controllers move request-handling logic out of route closures and into dedicated classes. This keeps routes clean and makes feature behavior easier to test.
MVC in Laravel, in practical terms
Laravel follows an MVC-style structure:
- Model: data and domain representation (usually Eloquent models in
app/Models). - View: presentation layer (Blade templates in
resources/views). - Controller: request orchestration (classes in
app/Http/Controllers).
Controller code should coordinate work, not contain all business rules itself.
flowchart LR
A[Request] --> B[Route]
B --> C[Controller]
C --> D[Model or service]
C --> E[View or JSON response]
First controller example
Create a controller:
php artisan make:controller HomeController
Add an action:
namespace App\\Http\\Controllers;
class HomeController extends Controller
{
public function index()
{
return view('home');
}
}
Use it in routes/web.php:
use App\\Http\\Controllers\\HomeController;
Route::get('/home', [HomeController::class, 'index'])->name('home');
Why this structure helps
- routes stay declarative,
- controller actions become easy to test,
- logic can later move into services without route rewrites,
- MVC boundaries make code reviews clearer.
In later chapters, you will deepen each MVC part, models (data), views (presentation), and controller/service architecture.
From Laravel best practices — What is Laravel?