Laravel Tutorial #3: The MVC Structure

Please note that this post may contain affiliate links, and for every purchase you make, at no extra cost to you, a commission fee will be rewarded to me.

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.

Controllers

Here is a link to the controller section of the official documentation: https://laravel.com/docs/8.x/controllers

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

<?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:

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/

img

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:

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.

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.

<html>
    <head>
        @yield('meta')
    </head>
    <body>

        @section('sidebar')

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>

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.

@extends('master')

@section('meta')
    <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">
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection

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.

Syntax

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!
@else
    I don't have any records!
@endif

Switch Statements

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

@switch($i)
    @case(1)
        First case...
        @break

    @case(2)
        Second case...
        @break

    @default
        Default case...
@endswitch

Loops

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 }}
@endfor

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

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

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

Models

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:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Test extends Model
{
    //
}
<?php

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) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('tests');
    }
}

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')
               ->take(10)
               ->get();

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

Tags:

Leave a Reply

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