Laravel Tutorial #3: The MVC Structure

More Tutorials on Web Development

Introducing the MVC Structure

The MVC structure means that the application is divided into three parts. The (M) model defines the data model, (V) view presents data and (C) controller defines logic and manipulates data.

The MVC structure


Here is a link to the controller section of the official documentation:

Basic Controllers

A controller is a place where you organize the behaviours of your app. For example, when the router receives “/“, it returns a “IndexController“.

The “IndexController” retrieves required information from the database, and then put them in the corresponding location of a view, and finally returns the view to the browser.

This is the most basic use of a controller. Of course, it can do a lot more than that, and I will talk about them as we encounter specific problems later in the tutorial.

To create our first controller. Go to the terminal, type in:

php artisan make:controller IndexController

Go to app/Http/Controllers/, and you will find a IndexController.php

namespace App\Http\Controllers;
use Illuminate\Http\Request;

class IndexController extends Controller

Note that the controller extends the base controller class included with Laravel. The base class provides a few convenience methods such as the middleware method.

We can try to make it return a string by creating a function inside the class:

class IndexController extends Controller
    public function index()
        return 'this is a controller';

We created a method called index(), and inside the method, it returns a string 'this is a controller'.

In order to test our code, we need to make a router return the “IndexController“. Go back to web.php, and create a new router like this:

use App\Http\Controllers\IndexController;

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

Notice the second argument is no longer a function, it is [IndexController::class, 'index'], which means go to the IndexController, find the index() method, and execute whatever is in it.

In the browser, go to http://localhost/

This is a controller

We can also make the IndexController to return a view.

class IndexController extends Controller
    public function index()
        return view('welcome');

Refresh the browser, this will get us the same result as we did in the previous article:

Laravel welcome page

Single Action Controllers

Single action controllers are useful when we only need one method in the controller class:

class IndexController extends Controller
    public function __invoke()
        return view('welcome');

Now we can change the route we just defined. We no longer need to specify the method.

Route::get('/', IndexController::class);

This code will work exactly the same as before.

Laravel welcome page

Views (Blade Templates)

Let’s reexamine the view welcome.blade.php, you will notice it is just an HTML file. Yes, views are based on HTML and CSS since they are what you see in the browser, but things are slightly more complicated than that.

If it contains only HTML codes, the entire blog would be static, and that is not what we want. So the view would have to “tell” the controller where to put the data it retrieved.

Template Inheritance

Define A Master Layout

The primary benefit of using the Blade template is that we do not need to write the same code over and over again. Let’s create a master.blade.php file in the templates folder.



        <div class="container">

Notice the two directives @section and @yield. The @section('sidebar') means Laravel will look for a blade template named “sidebar.blade.php“, and import it here. The @yield directive is used to display the contents of a given section.

Extend A Layout

Here, we create another view index.blade.php.


    <meta charset="UTF-8">
    <meta name="description" content="Free Web tutorials">
    <meta name="keywords" content="HTML, CSS, JavaScript">
    <meta name="author" content="John Doe">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <p>This is my body content.</p>

When this view is called, Laravel will look for the master blade template we just created. Replace @yield('meta') with the meta section, and replace @yield('content') with the content section.

With these two directives, we are able to build any type of template hierarchy we want.


Displaying Data

Let’s first make some changes to our IndexController:

class IndexController extends Controller
    public function __invoke()
        return view('index', ['name' => 'Eric']);

we defined a variable name here, and its value is Eric. Remember, this is also the new syntax in Laravel 8.

In the index view, we change the content section into this:

<p>Hello, {{ $name }}.</p>

The output will be Hello, Eric..

If Statements

You may construct if statements using the @if@elseif@else, and @endif directives. These directives function identically to their PHP counterparts:

@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
    I don't have any records!

Switch Statements

Switch statements can be constructed using the @switch@case@break@default and @endswitch directives:

        First case...

        Second case...

        Default case...


In addition to conditional statements, Blade provides simple directives for working with PHP’s loop structures. Again, each of these directives functions identically to their PHP counterparts:

@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}

@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
    <p>No users</p>

@while (true)
    <p>I'm looping forever.</p>


Remember I said controllers are in charge of retrieving data from the database? Well, that’s where models come in.

Each database table has a corresponding “Model”, and that model will handle all the interactions with the table.

Define Models

The easiest way to create a model instance is using the make:model Artisan command:

php artisan make:model Test

If you want to generate the corresponding migration files, you may use the --migration or -m option:

php artisan make:model Test --migration

php artisan make:model Test -m

Here is an example of a model and migration file:


namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Test extends Model

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTestsTable extends Migration
     * Run the migrations.
     * @return void
    public function up()
        Schema::create('tests', function (Blueprint $table) {

     * Reverse the migrations.
     * @return void
    public function down()

We won’t go into details about these right now since it can be quite confusing for beginners. Instead, we’ll talk about them with real examples later in the tutorial.

Retrieve Data

Laravel has an elegant way of retrieving data, with Eloquent. Think of each Eloquent model as a powerful query builder allowing you to fluently query the database table associated with the model.

$flights = App\Models\Flight::where('active', 1)
               ->orderBy('name', 'desc')

Again, we’ll go into details about this later.

11 thoughts on “Laravel Tutorial #3: The MVC Structure”

  1. Hello.

    About: “Let’s first make some changes to our IndexController:”

    Than you change to: public function __invoke()

    This returns error: Method App\Http\Controllers\IndexController::index does not exist.

    Did you meant: public function index()


    Thank you.

  2. Hey Eric. Thanks for the tutorial. You had missed adding the IndexController to the web.php route.

    use AppHttpControllersIndexController;

    1. If you are using PyCharm, the “templates” directory should be automatically created for you. If not, you can still create your own, but you have to specify the path in the file.

    1. It is like the do while loop in other languages. In this case, it first check if the $user exist, if it does, printout

    2. {{ $user->name }}
    3. , if not, printout

      No users


Leave a Reply

Your email address will not be published. Required fields are marked *