Skip to main content

πŸ›οΈ Laravel Framework Architecture

Laravel is the most widely used PHP framework, and its power comes from a small set of ideas working together. Before you write routes and controllers, it pays to see how a request flows through the framework β€” from the front controller, through the service container, into your code, and back out as a response.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Explain the MVC pattern and identify the model, view, and controller in a Laravel app
  • Trace the request lifecycle from public/index.php to the HTTP response
  • Describe what the service container does and why dependency injection matters
  • Navigate Laravel's directory structure and know where each kind of code lives
  • Recognize the role of service providers and the broader Laravel ecosystem

Estimated Time: 35–45 minutes  β€’  Difficulty: Intermediate

Hands-on: Scaffold a fresh Laravel app and trace a single request through every layer.

In This Lesson

What Is Laravel?

Laravel is a free, open-source PHP web framework created by Taylor Otwell in 2011. It is by a wide margin the most popular PHP framework today, valued for its expressive syntax, its "batteries-included" feature set, and a design that consistently favours convention over configuration β€” sensible defaults that get out of your way until you need to change them.

Think of Laravel as a well-organised professional kitchen. A home cook can make dinner with one pot and a single knife (raw PHP), but a professional kitchen gives you dedicated stations, sharp tools within reach, and a clear workflow so you spend your energy on the food, not on hunting for equipment. Laravel provides routing, an ORM, a templating engine, authentication, queues, testing tools, and more β€” already wired together.

πŸ’‘ The framework's own promise: Laravel describes itself as a framework with "expressive, elegant syntax" whose foundation is already laid so you can build without sweating the small things. This lesson is about understanding that foundation.

πŸ“– Key Terms

Framework: a reusable skeleton of code that provides structure and common features so you write only what is unique to your app.

Convention over configuration: the framework assumes a standard layout and naming, so you configure only the exceptions.

Artisan: Laravel's command-line tool (php artisan …) used to generate code, run migrations, and manage the app.

This course targets a current Laravel release (Laravel 11+ on PHP 8.2 or newer). Recent versions slimmed the default skeleton considerably β€” for example, HTTP middleware and exception handling are now configured in bootstrap/app.php rather than a large Kernel class. We will point out these modern conventions as we go.

The MVC Pattern

Laravel is built around Model–View–Controller (MVC), an architecture that splits an application into three cooperating roles. Separating them keeps presentation, logic, and data independent, so each can change without breaking the others.

flowchart LR A[HTTP Request] --> B[Route] B --> C[Controller] C --> D[Model] D --> E[(Database)] E --> D D --> C C --> F[View] F --> G[HTTP Response]
RoleResponsibilityIn Laravel
ModelData and business rules; talks to the databaseEloquent models in app/Models
ViewPresentation β€” the HTML the user seesBlade templates in resources/views
ControllerCoordinates: receives the request, calls models, returns a viewClasses in app/Http/Controllers

A restaurant makes the roles intuitive: the model is the kitchen and pantry (where the real work with ingredients/data happens), the view is the beautifully plated dish handed to the guest, and the controller is the waiter who takes the order, relays it to the kitchen, and brings the finished plate back.

βœ… Keep controllers thin

A common beginner mistake is stuffing business logic into controllers. The healthiest Laravel apps keep controllers small β€” they coordinate β€” and push real logic into models, dedicated service classes, or actions. You will feel the payoff when the app grows and needs tests.

The Request Lifecycle

Every request to a Laravel app follows the same journey. Understanding it demystifies almost every "where does this happen?" question you will ever ask.

sequenceDiagram participant U as Browser participant I as public/index.php participant K as App Kernel participant M as Middleware participant R as Router participant C as Controller U->>I: HTTP Request I->>K: Bootstrap the app K->>M: Run global middleware M->>R: Match the route R->>M: Run route middleware M->>C: Dispatch to controller C-->>U: HTTP Response
  1. Entry point. The web server sends every request to public/index.php β€” the single "front controller." Nothing else in your project is web-accessible.
  2. Bootstrap. Laravel loads the framework, reads your configuration, and prepares the service container (next section).
  3. Middleware. The request passes through layers such as CSRF protection, session handling, and authentication β€” each can inspect, modify, or reject it.
  4. Routing. The router matches the URL and HTTP verb to a route and its handler.
  5. Controller. The matched controller method runs, usually asking one or more models for data.
  6. Response. The handler returns a response β€” a rendered view, JSON, a redirect, or a file β€” which travels back out through the middleware to the browser.

It resembles mail delivery: your letter (the request) passes through a series of sorting and security centres (middleware) before reaching the right desk (controller), which then posts a reply (the response) back along the same route.

Service Container & Dependency Injection

The service container (also called the IoC container) is the engine at Laravel's core. Its job is to create objects and to automatically supply the other objects they depend on β€” a technique called dependency injection.

Instead of a class reaching out and constructing its own dependencies, it simply declares what it needs in its constructor, and the container provides them. This keeps classes loosely coupled and dramatically easier to test.

<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
    // Type-hint the dependency in the constructor β€”
    // Laravel's container resolves and injects it automatically.
    public function __construct(
        private readonly UserRepository $users
    ) {}

    public function show(int $id)
    {
        return view('users.show', [
            'user' => $this->users->find($id),
        ]);
    }
}

Notice the modern PHP 8 constructor property promotion (private readonly UserRepository $users) β€” the parameter is declared and stored as a property in one step. You never write new UserRepository(); the container does it for you.

πŸ’‘ Analogy: The container is a skilled assistant who knows where every tool lives. You say "I need a user repository and a logger," and they are placed in your hands β€” you never rummage through drawers yourself.

βœ… Why this matters

Because dependencies are injected rather than hard-coded, you can swap a real implementation for a fake one in tests, or change how something is built in one central place. This is the foundation of Laravel's testability and flexibility.

Directory Structure

Laravel's folder layout mirrors its architecture. Once you internalise it, you always know where to look β€” and where new code belongs.

app/                  # Your application code
β”œβ”€β”€ Http/
β”‚   β”œβ”€β”€ Controllers/  # Controllers
β”‚   β”œβ”€β”€ Middleware/   # Custom middleware
β”‚   └── Requests/     # Form request (validation) classes
β”œβ”€β”€ Models/           # Eloquent models
β”œβ”€β”€ Providers/        # Service providers
bootstrap/
β”œβ”€β”€ app.php           # App creation + middleware/exception config (Laravel 11+)
config/               # Configuration files
database/
β”œβ”€β”€ migrations/       # Schema definitions
β”œβ”€β”€ seeders/          # Sample/seed data
└── factories/        # Model factories for testing
public/               # Web root β€” index.php + compiled assets
resources/
β”œβ”€β”€ views/            # Blade templates
β”œβ”€β”€ js/  css/         # Frontend source assets
routes/
β”œβ”€β”€ web.php           # Web routes (sessions, CSRF)
β”œβ”€β”€ console.php       # Artisan command definitions
└── api.php           # API routes (added via install:api)
storage/              # Logs, cache, compiled views, uploads
tests/                # Automated tests
vendor/               # Composer dependencies (never edited or committed)

It is like a well-run office building where every department has a known floor. You would not search for the accounting team on the loading dock β€” and you would not look for a controller in resources/.

⚠️ Two folders to treat carefully

vendor/ holds third-party packages installed by Composer β€” never edit it, and keep it out of version control. storage/ holds generated files (logs, caches, uploads); your web server needs write access to it.

Service Providers

Service providers are the central place where the framework and your app are wired together. During bootstrap, each provider gets a chance to register things into the container and then to boot β€” run setup once everything is registered.

<?php

namespace App\Providers;

use App\Services\PaymentGateway;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        // Bind services into the container.
        // singleton() ensures the same instance is reused everywhere.
        $this->app->singleton(PaymentGateway::class, function ($app) {
            return new PaymentGateway(config('services.payment'));
        });
    }

    public function boot(): void
    {
        // Runs after ALL providers are registered.
        // A good place to configure things that depend on other services.
    }
}

The two methods have a strict order and purpose:

  • register() β€” only bind things into the container here. Do not assume other services exist yet.
  • boot() β€” runs after every provider has registered, so all bindings are available. Configure views, define validation rules, register event listeners, etc.

If a Laravel app were a theatre production, service providers would be the stage crew: they set up every prop and light before the curtain rises (before a request is handled) so the performance runs without a hitch.

The Laravel Ecosystem

Laravel is more than a framework β€” it is a family of official packages and tools that snap together with the core. You do not need them to start, but knowing they exist tells you what problems are already solved for you.

ToolSolves
EloquentThe built-in ORM for elegant database access (a later lesson)
BladeThe templating engine for views (the next-next lesson)
SanctumLightweight API / SPA token authentication
Breeze / JetstreamStarter kits with ready-made authentication scaffolding
HorizonDashboard and monitoring for Redis-backed queues
TelescopeLocal debugging: inspect requests, queries, jobs, and more
Forge / VaporServer provisioning and serverless deployment
DuskBrowser (end-to-end) testing

This integrated approach is like a single manufacturer's product line: each tool is designed to work seamlessly with the core, so adopting one rarely means fighting the others.

πŸ’‘ How Laravel compares

Among PHP frameworks, Symfony is more component-oriented and common in large enterprises; Laravel favours developer speed and a cohesive experience. Compared with Node's Express, Laravel is a "full framework" (ORM, templating, auth all included) rather than a minimal, middleware-based library. Different trade-offs β€” the same web fundamentals underneath.

Hands-on Exercise

πŸ‹οΈ Scaffold and Trace a Request

Objective: Create a fresh Laravel app, add one route, and follow a single request through every architectural layer you just learned.

Instructions:

  1. Create a new project (requires PHP 8.2+ and Composer):
    composer create-project laravel/laravel example-app
    cd example-app
    php artisan serve
  2. Open the project and locate public/index.php, bootstrap/app.php, routes/web.php, and app/Http/Controllers.
  3. Generate a controller:
    php artisan make:controller WelcomeController
  4. Add a method that returns a view, and register a route for it in routes/web.php.
  5. On paper, list the six lifecycle steps and write, for your route, exactly which file handles each step.
πŸ’‘ Hint

A controller method returning a view looks like return view('welcome');. Register it with Route::get('/hi', [WelcomeController::class, 'index']); and remember to use App\Http\Controllers\WelcomeController; at the top of the routes file.

βœ… Example solution
<?php
// app/Http/Controllers/WelcomeController.php
namespace App\Http\Controllers;

class WelcomeController extends Controller
{
    public function index()
    {
        return view('welcome', ['name' => 'Ray']);
    }
}
<?php
// routes/web.php
use App\Http\Controllers\WelcomeController;
use Illuminate\Support\Facades\Route;

Route::get('/hi', [WelcomeController::class, 'index']);

Trace: browser β†’ public/index.php (entry) β†’ bootstrap/app.php (bootstrap + middleware) β†’ router matches /hi in routes/web.php β†’ WelcomeController@index runs β†’ returns the welcome Blade view β†’ response travels back to the browser.

🎯 Quick Quiz

Question 1: In Laravel's MVC pattern, which component is responsible for coordinating the request β€” calling models and returning a view?

Question 2: Which single file is the entry point that every web request to a Laravel app passes through first?

Question 3: What is the primary job of Laravel's service container?

Summary & Quiz

πŸŽ‰ Key Takeaways

  • Laravel is a "batteries-included" PHP framework built on convention over configuration.
  • It follows MVC: models hold data/logic, views present, controllers coordinate.
  • Every request follows the same lifecycle: entry point β†’ bootstrap β†’ middleware β†’ routing β†’ controller β†’ response.
  • The service container creates objects and injects dependencies, enabling loose coupling and testability.
  • The directory structure and service providers give every kind of code a predictable home and wire the app together.

πŸ“š Further Reading

πŸš€ What's Next?

Now that you can trace a request through the framework, the next lesson zooms in on the two layers you will touch most often: routing and controllers β€” how URLs map to your code and how controllers process what arrives.

πŸŽ‰ Great start!

You now hold the architectural map of Laravel. Everything else in this module fills it in.