Appearance
Meeting 12 - MVC Concept in Laravel
Goal: Understand Laravel's Model–View–Controller (MVC) architecture: how a request flows through the framework, where each type of code lives, and a minimal example that ties the pieces together.
1. What is MVC?
MVC (Model–View–Controller) is an architectural pattern that separates responsibilities:
- Model: Data representation + business logic (Eloquent ORM: relationships, queries, accessors/mutators, etc.).
- View: Presentation layer (Blade templates) that renders HTML returned to the user (or components/fragments reused across pages).
- Controller: Coordinates the request: receives input, calls the Model, chooses the View (or returns JSON / redirect / file response).
This separation improves readability, testability, scalability, and teamwork velocity.
2. Request Flow in Laravel
- Browser (or API client) sends an HTTP request.
- The single entry point
public/index.phpboots the framework (service providers, environment, autoload, etc.). - The router matches the URL + HTTP method against definitions in
routes/web.php(HTML) orroutes/api.php(API/JSON). - The matched route invokes a Controller method (or a closure / invokable class / middleware pipeline).
- The Controller interacts with Models (Eloquent) to read or persist data.
- The Controller returns a response: a Blade view, JSON, redirect, file, stream, etc.
- The HTTP response is sent back to the client.
3. Diagram

4. Relevant Folders
text
app/
Models/ # Eloquent models (User, Article, etc.)
Http/
Controllers/ # Controllers (ArticleController, Auth\LoginController, ...)
resources/
views/ # Blade templates (*.blade.php)
routes/
web.php # Web routes (HTML responses)
api.php # API routes (stateless / JSON)
database/
migrations/ # Table structure definitions
seeders/ # Initial or sample data population
public/
index.php # Front controller (entry point)app/
Models/ # Eloquent models (User, Article, etc.)
Http/
Controllers/ # Controllers (ArticleController, Auth\LoginController, ...)
resources/
views/ # Blade templates (*.blade.php)
routes/
web.php # Web routes (HTML responses)
api.php # API routes (stateless / JSON)
database/
migrations/ # Table structure definitions
seeders/ # Initial or sample data population
public/
index.php # Front controller (entry point)5. Minimal Example: Article Listing & Create
We will build only the essential pieces to illustrate how MVC connects: show a paginated list and create new articles.
5.1 Migration
Generate the migration:
bash
php artisan make:migration create_articles_tablephp artisan make:migration create_articles_tableExample content (file in database/migrations/xxxx_xx_xx_xxxxxx_create_articles_table.php):
php
public function up(): void
{
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->timestamps();
});
}public function up(): void
{
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->timestamps();
});
}Run it:
bash
php artisan migratephp artisan migrate5.2 Model
bash
php artisan make:model Articlephp artisan make:model Articleapp/Models/Article.php:
php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
protected $fillable = ['title', 'body'];
}namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
protected $fillable = ['title', 'body'];
}5.3 Controller
bash
php artisan make:controller ArticleControllerphp artisan make:controller ArticleControllerapp/Http/Controllers/ArticleController.php:
php
namespace App\Http\Controllers;
use App\Models\Article;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
public function index()
{
$articles = Article::latest()->paginate(5); // fetch data from DB
return view('articles.index', compact('articles')); // pass to Blade view
}
public function create()
{
return view('articles.create');
}
public function store(Request $request)
{
$data = $request->validate([
'title' => 'required|min:3',
'body' => 'required|min:10'
]);
Article::create($data); // persist through Model
return redirect()->route('articles.index')->with('success', 'Article created.');
}
}namespace App\Http\Controllers;
use App\Models\Article;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
public function index()
{
$articles = Article::latest()->paginate(5); // fetch data from DB
return view('articles.index', compact('articles')); // pass to Blade view
}
public function create()
{
return view('articles.create');
}
public function store(Request $request)
{
$data = $request->validate([
'title' => 'required|min:3',
'body' => 'required|min:10'
]);
Article::create($data); // persist through Model
return redirect()->route('articles.index')->with('success', 'Article created.');
}
}5.4 Routes
Edit routes/web.php:
php
use App\Http\Controllers\ArticleController;
Route::get('/articles', [ArticleController::class, 'index'])->name('articles.index');
Route::get('/articles/create', [ArticleController::class, 'create'])->name('articles.create');
Route::post('/articles', [ArticleController::class, 'store'])->name('articles.store');use App\Http\Controllers\ArticleController;
Route::get('/articles', [ArticleController::class, 'index'])->name('articles.index');
Route::get('/articles/create', [ArticleController::class, 'create'])->name('articles.create');
Route::post('/articles', [ArticleController::class, 'store'])->name('articles.store');(Full RESTful alternative: Route::resource('articles', ArticleController::class);)
5.5 Views (Blade)
resources/views/articles/index.blade.php:
blade
@extends('layouts.app')
@section('content')
<h1>Articles</h1>
<a href="{{ route('articles.create') }}">+ New Article</a>
@if(session('success'))
<div class="alert">{{ session('success') }}</div>
@endif
@foreach($articles as $article)
<article style="margin-bottom:1rem;">
<h2>{{ $article->title }}</h2>
<p>{{ Str::limit($article->body, 120) }}</p>
<small>Published: {{ $article->created_at->diffForHumans() }}</small>
</article>
@endforeach
{{ $articles->links() }}
@endsection@extends('layouts.app')
@section('content')
<h1>Articles</h1>
<a href="{{ route('articles.create') }}">+ New Article</a>
@if(session('success'))
<div class="alert">{{ session('success') }}</div>
@endif
@foreach($articles as $article)
<article style="margin-bottom:1rem;">
<h2>{{ $article->title }}</h2>
<p>{{ Str::limit($article->body, 120) }}</p>
<small>Published: {{ $article->created_at->diffForHumans() }}</small>
</article>
@endforeach
{{ $articles->links() }}
@endsectionresources/views/articles/create.blade.php:
blade
@extends('layouts.app')
@section('content')
<h1>Create Article</h1>
<form method="POST" action="{{ route('articles.store') }}">
@csrf
<div>
<label>Title</label>
<input type="text" name="title" value="{{ old('title') }}" />
@error('title') <small style="color:red;">{{ $message }}</small> @enderror
</div>
<div>
<label>Body</label>
<textarea name="body" rows="6">{{ old('body') }}</textarea>
@error('body') <small style="color:red;">{{ $message }}</small> @enderror
</div>
<button type="submit">Save</button>
</form>
@endsection@extends('layouts.app')
@section('content')
<h1>Create Article</h1>
<form method="POST" action="{{ route('articles.store') }}">
@csrf
<div>
<label>Title</label>
<input type="text" name="title" value="{{ old('title') }}" />
@error('title') <small style="color:red;">{{ $message }}</small> @enderror
</div>
<div>
<label>Body</label>
<textarea name="body" rows="6">{{ old('body') }}</textarea>
@error('body') <small style="color:red;">{{ $message }}</small> @enderror
</div>
<button type="submit">Save</button>
</form>
@endsection5.6 Simple Layout (Optional)
resources/views/layouts/app.blade.php:
blade
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Mini Blog</title>
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css" />
</head>
<body>
<nav>
<a href="/articles">Articles</a>
<a href="/articles/create">Create</a>
</nav>
<main>
@yield('content')
</main>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Mini Blog</title>
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css" />
</head>
<body>
<nav>
<a href="/articles">Articles</a>
<a href="/articles/create">Create</a>
</nav>
<main>
@yield('content')
</main>
</body>
</html>6. Component Roles (Summary)
| Component | Example | Responsibility |
|---|---|---|
| Route | /articles | Maps URL + method to controller action |
| Controller | ArticleController@index | Orchestrates data fetch & selects view |
| Model | Article | Encapsulates table articles, queries & business rules |
| Migration | create_articles_table | Defines database structure |
| View | articles/index.blade.php | Renders HTML output |
7. Quick Best Practices
- Keep controllers thin: move heavy logic to Models, Query Objects, or dedicated Services.
- Prefer resource controllers for conventional CRUD routing.
- Extract validation into Form Request classes (
php artisan make:request). - Leverage Eloquent relationships (hasMany, belongsTo, etc.) for readable queries.
- Reuse UI via Blade components / includes / layouts.
8. CRUD Flow (Create & List)
GET /articles -> route -> controller@index -> Article::latest() -> Blade view -> HTML response
GET /articles/create -> route -> controller@create -> Blade form view
POST /articles -> route -> controller@store -> validate -> Article::create() -> redirectGET /articles -> route -> controller@index -> Article::latest() -> Blade view -> HTML response
GET /articles/create -> route -> controller@create -> Blade form view
POST /articles -> route -> controller@store -> validate -> Article::create() -> redirect