© Sanjib Sinha 2019
S. SinhaBeginning Laravel https://doi.org/10.1007/978-1-4842-4991-8_3

3. Routing, Controllers, Templates, and Views

Sanjib Sinha1 
(1)
Howrah, West Bengal, India
 

In the previous two chapters, you learned how to create your environment so that you can use Composer to install fresh Laravel applications, and you learned many more other nitty-gritty details of Laravel. You also are now familiar with the concepts of the Model-View-Controller (MVC) logic system.

In this chapter, you will learn how Laravel follows the MVC pattern.

To enter an application, you need to have an entry point. The basic algebraic definition of function works here: you give input to a function, and you get output. When applying this to Laravel, you can replace the word input with request and replace the word output with response.

To start creating a Laravel application, the web.php file in the routes directory is important. It takes the requests from you, the user, and sends them to either a closure that gives a response, a view page that displays the response, or a controller that does the same thing; in some critical cases, the controller consults with the model and then is updated by the business logic.

You will learn all about this mechanism in this chapter.

Route Definitions

Laravel must know how to respond to a particular request, which relates to the concept of routing. Here is a basic example of routing a request:
//code 3.1
//routes/web.php
Route::get('/', function () {
    return view('welcome');
});

In this example, the Laravel route accepts a URI through the HTTP GET method using a closure. The closure (also called an anonymous function) returns a view page. I will come back to that in a minute, but I need to point out one more thing here: the Route class uses a static method, which is a class-level method. Why does it not use an instance of Route? This is because a class-level variable consumes less memory than objects, whereas an object, once instantiated, starts consuming memory. This is an important concept of object-oriented programming.

This file defines the application’s URL endpoints so Laravel knows how to respond to that request. Here the URI is the document root or home page, and the Closure or anonymous function returns a view that contains an HTML page. These views are called view pages , and they are based on the Blade template engine that Laravel ships with.

This is a simple and expressive method of defining routes where models and controllers are absent. However, in a real-world scenario, you keep controllers between models and views, and the routes are initiated by the controllers. You will see an example of that in a few minutes.

You could have written the previous code in this way:
//code 3.2
//routes/web.php
Route::get('/', 'WelcomeController@index');

In the previous code, inside the welcome controller’s index method, you can return the same view.

How to Find the Default Route Files

The Laravel framework automatically loads the route files in the routes directory. For the web interface, the routes/web.php file defines the routes. In Chapter 3, you will see how these routes are assigned to the web middleware group. Actually, route provides many features such as session state and CSRF protection. There is another middleware group, called api. I will also discuss this group later in this chapter.

In most cases, you will start by using this routes/web.php file . However, using closures is not a workable option. In some special cases, you will definitely use closures, but you will normally use a dedicated controller to manage a connected resource, as I showed in the previous code snippet.

Let’s think about a TaskController. This controller might retrieve all tasks. It gets all tasks views, inserts a new task, edits and updates an existing task, and finally deletes an existing list from the database.

Route and RESTful Controller

Since you will normally use a dedicated controller to manage a connected resource, the concept of RESTful or resourceful controllers applies here. In the “Resourceful Controller” section, I will discuss resourceful controllers in more detail, but before that, all you need to know is that a RESTful or resourceful controller can handle all seven routes associated with it. For now, you should know that when you use a create-read-update-delete (CRUD) approach, you use HTTP methods such as GET, POST, PUT, and DELETE. How do you get seven routes from this? Well, you use GET four times: to show all content, to show a form to create new content, to show a particular piece of content (ideally getting that by its ID), and finally to show the edit form to update the content.

You can write a route like this:
//code 3.3
//routes/web.php
Route::resource('tasks', 'TaskController');

Now, you can view all the tasks by typing http://example.com/tasks in your browser because the controller is waiting for the request and is programmed to display all the tasks.

What does the term RESTful mean? There is a fundamental difference between a web application and a REST API. When you get the response from a web application, it generally consists of HTML, CSS, and JavaScript. On the other hand, the REST API returns data in the form of JSON or XML. As you progress, you will learn more about the close relationship between Laravel and JSON output.

How to List All Routes

In a large application, it is quite cumbersome to maintain a list of all the routes. There might be hundreds of routes, and they are connected to dedicated resources with separate business logic.

Laravel has made it easy to list all routes by using a single command. I will show you one small application where I have maintained a few controllers and view pages. There is an administrator section, and I can create, retrieve, update, and delete (CRUD) articles through that admin panel, and I can also add some tasks. For doing these simple operations, I have created three controllers and made them all resourceful. Now if you issue a single command to get the route lists, like this:
//code 3.4
$ php artisan route:list
it will give you some output like Figure 3-1.
../images/435350_2_En_3_Chapter/435350_2_En_3_Fig1_HTML.jpg
Figure 3-1

List of all routes in an application

Figure 3-1 shows a table where the column names are Method, URI, Name, Action, and Middleware. In the following code, you will see the method name first, which is either GET, POST, PUT, or DELETE. After that, you will see the URI, such as /adminpage; next comes the view page names like adminpage.show. This is followed by the action or controller methods, like AdminController@index, and at the end comes the middleware. I will talk about the middleware later in the book in great detail.
ss@ss-H81M-S1:~/code/twoprac/freshlaravel57$ php artisan route:list
+--------+-----------+----------------------------+-------------------+------------------------------------------------------------------------+--------------+
| Domain | Method    | URI                        | Name              | Action                                                                 | Middleware   |
+--------+-----------+----------------------------+-------------------+------------------------------------------------------------------------+--------------+
|        | GET|HEAD  | /                          |                   | Closure                                                                | web          |
|        | GET|HEAD  | adminpage                  | adminpage.index   | AppHttpControllersAdminController@index                             | web,auth     |
|        | POST      | adminpage                  | adminpage.store   | AppHttpControllersAdminController@store                             | web,auth     |
|        | GET|HEAD  | adminpage/create           | adminpage.create  | AppHttpControllersAdminController@create                            | web,auth     |
|        | DELETE    | adminpage/{adminpage}      | adminpage.destroy | AppHttpControllersAdminController@destroy                           | web,auth     |
|        | PUT|PATCH | adminpage/{adminpage}      | adminpage.update  | AppHttpControllersAdminController@update                            | web,auth     |
|        | GET|HEAD  | adminpage/{adminpage}      | adminpage.show    | AppHttpControllersAdminController@show                              | web,auth     |
|        | GET|HEAD  | adminpage/{adminpage}/edit | adminpage.edit    | AppHttpControllersAdminController@edit                              | web,auth     |
|        | GET|HEAD  | api/user                   |                   | Closure                                                                | api,auth:api |
|        | POST      | articles                   | articles.store    | AppHttpControllersArticleController@store                           | web,auth     |
|        | GET|HEAD  | articles                   | articles.index    | AppHttpControllersArticleController@index                           | web,auth     |
|        | GET|HEAD  | articles/create            | articles.create   | AppHttpControllersArticleController@create                          | web,auth     |
|        | PUT|PATCH | articles/{article}         | articles.update   | AppHttpControllersArticleController@update                          | web,auth     |
|        | GET|HEAD  | articles/{article}         | articles.show     | AppHttpControllersArticleController@show                            | web,auth     |
|        | DELETE    | articles/{article}         | articles.destroy  | AppHttpControllersArticleController@destroy                         | web,auth     |
|        | GET|HEAD  | articles/{article}/edit    | articles.edit     | AppHttpControllersArticleController@edit                            | web,auth     |
|        | GET|HEAD  | home                       | home              | AppHttpControllersHomeController@index                              | web,auth     |
|        | GET|HEAD  | login                      | login             | AppHttpControllersAuthLoginController@showLoginForm                | web,guest    |
|        | POST      | login                      |                   | AppHttpControllersAuthLoginController@login                        | web,guest    |
|        | POST      | logout                     | logout            | AppHttpControllersAuthLoginController@logout                       | web          |
|        | POST      | password/email             | password.email    | AppHttpControllersAuthForgotPasswordController@sendResetLinkEmail  | web,guest    |
|        | GET|HEAD  | password/reset             | password.request  | AppHttpControllersAuthForgotPasswordController@showLinkRequestForm | web,guest    |
|        | POST      | password/reset             | password.update   | AppHttpControllersAuthResetPasswordController@reset                | web,guest    |
|        | GET|HEAD  | password/reset/{token}     | password.reset    | AppHttpControllersAuthResetPasswordController@showResetForm        | web,guest    |
|        | GET|HEAD  | register                   | register          | AppHttpControllersAuthRegisterController@showRegistrationForm      | web,guest    |
|        | POST      | register                   |                   | AppHttpControllersAuthRegisterController@register                  | web,guest    |
|        | POST      | tasks                      | tasks.store       | AppHttpControllersTaskController@store                              | web,auth     |
|        | GET|HEAD  | tasks                      | tasks.index       | AppHttpControllersTaskController@index                              | web          |
|        | GET|HEAD  | tasks/create               | tasks.create      | AppHttpControllersTaskController@create                             | web,auth     |
|        | GET|HEAD  | tasks/{task}               | tasks.show        | AppHttpControllersTaskController@show                               | web          |
|        | DELETE    | tasks/{task}               | tasks.destroy     | AppHttpControllersTaskController@destroy                            | web,auth     |
|        | PUT|PATCH | tasks/{task}               | tasks.update      | AppHttpControllersTaskController@update                             | web,auth     |
|        | GET|HEAD  | tasks/{task}/edit          | tasks.edit        | AppHttpControllersTaskController@edit                               | web,auth     |
|        | GET|HEAD  | user                       |                   | Closure

Creating Controllers, Views, and Managing Routes

I have already pointed out why you need a controller. You cannot define all of your request handling logic as closures in route files. Instead, you can organize this action using controller classes. Controller class group related request handling logic into a single class. You can create a controller quite easily by keeping the connected resources in mind. Controllers can be stored in the app/Http/Controllers directory.

Let’s create a controller first, as shown here:
//code 3.5
$ php artisan make:controller TaskController --resource
//the output of code 3.5
Controller created successfully.
This is what the app/Http/Controllers/TaskController.php file looks like:
//code 3.6
// app/Http/Controllers/TaskController.php
<?php
namespace AppHttpControllers;
use IlluminateHttpRequest;
class TaskController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return IlluminateHttpResponse
     */
    public function index()
    {
        //
    }
    /**
     * Show the form for creating a new resource.
     *
     * @return IlluminateHttpResponse
     */
    public function create()
    {
        //
    }
    /**
     * Store a newly created resource in storage.
     *
     * @param  IlluminateHttpRequest  $request
     * @return IlluminateHttpResponse
     */
    public function store(Request $request)
    {
        //
    }
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function show($id)
    {
        //
    }
    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function edit($id)
    {
        //
    }
    /**
     * Update the specified resource in storage.
     *
     * @param  IlluminateHttpRequest  $request
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function update(Request $request, $id)
    {
        //
    }
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function destroy($id)
    {
        //
    }
}

There are seven methods that you need to create a CRUD system for your connected resources. Here the connected resources are the Task model , through which you will handle your database and business logic. The other parts of resources are your related views page through which you will handle all types of front-end operations such as showing tasks and creating, editing, and deleting your tasks.

While creating the TaskController, I have added an extra parameter called --resource. Because of that parameter, I get all seven CRUD methods in my TaskController. I could have created them manually, but Laravel takes care of creating them automatically because I passed that parameter while creating the Controller class.

Now, in your routes/web.php file, you can address all associated routes in a single line of code, as shown here:
//code 3.7
//routes/web.php
Route::resource('tasks', 'TaskController');

CRUD and the Seven Methods

The single line of code shown previously handles all seven methods created by default in the TaskController class.

If you issue the php artisan route:list command, you will see the related URIs, names, actions, and methods.

Let’s check it out. All seven methods, URIs, and names (related view pages) are as follows:
| GET|HEAD  | tasks                      | tasks.index
| POST      | tasks                      | tasks.store       |
| GET|HEAD  | tasks/create               | tasks.create      |
| GET|HEAD  | tasks/{task}               | tasks.show        |
| DELETE    | tasks/{task}               | tasks.destroy     |
| PUT|PATCH | tasks/{task}               | tasks.update      |
| GET|HEAD  | tasks/{task}/edit

Let’s try to understand how it works. When you type a URI like http://example.com/tasks in your browser, The ‘task resource’ sends the GET requests. The index.blade.php page belonging to the resources/views/tasks folder displays all tasks.

The third method is a GET, and the URI is http://example.com/tasks/create . It will display a form in the create.blade.php page belonging to the resources/views/tasks folder. Here you will fill up all the related fields and hit the Submit button. Once you do that, the second method will start acting. That is the POST, and you do not need to have the store.blade.php file. Laravel handles this POST request automatically in the TaskController class.

And it goes on like this.

To get a complete view, you need to see what your final TaskController.php file looks like, as shown here:
//code 3.8
// app/Http/Controllers/TaskController.php
<?php
namespace AppHttpControllers;
use AppTask;
use IlluminateSupportFacadesAuth;
use IlluminateHttpRequest;
class TaskController extends Controller
{
    /**
   * Create a new controller instance.
   *
   * @return void
   */
  public function __construct()
  {
      $this->middleware('auth')->except('index', 'show');
  }
    /**
     * Display a listing of the resource.
     *
     * @return IlluminateHttpResponse
     */
    public function index()
    {
        //
        $tasks = Task::get();
        return view('tasks.index', compact('tasks'));
    }
    /**
     * Show the form for creating a new resource.
     *
     * @return IlluminateHttpResponse
     */
    public function create()
    {
        //
        if(Auth::user()->is_admin == 1){
            return view('tasks.create');
        }
        else {
          return redirect('home');
        }
    }
    /**
     * Store a newly created resource in storage.
     *
     * @param  IlluminateHttpRequest  $request
     * @return IlluminateHttpResponse
     */
    public function store(Request $request)
    {
        //
        if(Auth::user()->is_admin == 1){
            $post = new Task;
  $post->title = $request->input('title');
  $post->body = $request->input('body');
  $post->save();
  if($post){
             return redirect('tasks');
         }
        }
    }
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function show($id)
    {
        //
        $task = Task::findOrFail($id);
        return view('tasks.show', compact('task'));
    }
    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function edit($id)
    {
        //
         if(Auth::user()->is_admin == 1){
        $task = Task::findOrFail($id);
        return view('tasks.edit', compact('task'));
      }
      else {
        // code...
        return redirect('home');
      }
    }
    /**
     * Update the specified resource in storage.
     *
     * @param  IlluminateHttpRequest  $request
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function update(Request $request, $id)
    {
        //
        if(Auth::user()->is_admin == 1){
            $post = Task::findOrFail($id);
  $post->title = $request->input('title');
  $post->body = $request->input('body');
  $post->save();
  if($post){
             return redirect('tasks');
         }
        }
    }
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return IlluminateHttpResponse
     */
    public function destroy($id)
    {
        //
    }
}

In the previous code, I skipped the destroy method, but it should give you an idea of how you can associate your controller class to a connected resource.

At the same time, you need to see the Task model and the database table that you have created so that this connection between the Model-Controller-View is complete.

First, while creating a model, you pass an extra parameter, -m, so that the database migration takes place automatically. Laravel creates the primary task and database table. (Of course, you can create them separately too.) While creating a connected resource with a controller class, it is a good idea to create the table with the Task model .
//code 3.9
//creating Task model and database table
$ php artisan make:model Task -m
Model created successfully.
Created Migration: 2019_02_16_041652_create_tasks_table

Now, you have successfully created the model and created the migration.

For brevity, I have kept this model and the migration tasks table quite simple. So, to create a model and related database table, you need to issue the command php artisan make:model Task -m. Only after that are the model and the related database table created.

Here is what the Task model looks like:
//code 3.10
//app/Task.php
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Task extends Model
{
    //
    protected $fillable = [
        'title', 'body'
    ];
}

After running the previous command, you get a task table in the database/migration folder. Now you can add more functionality to that table by adding new columns. After the modification, you will issue another command so that Laravel knows that it should take the necessary steps to modify it.

You can modify the database migration tasks table as follows:
//code 3.11
// database/migrations/tasks table
<?php
use IlluminateSupportFacadesSchema;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;
class CreateTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

Now, your route, model, controller, and view circle is complete. You will learn how each of these components works in later chapters. Understand that you should have the resources as separate as possible. They must be loosely coupled so that each controller has a connected model and view pages.

Models Acts as a Resource

Now through the Model class you can build bridges to the other parts of your application. But that is a different thing. I will discuss later how Eloquent relationships work and how each database table communicates with each other.

In the code for the TaskController class (code 3.8), you saw lines like this:
//code 3.12
public function __construct()
  {
      $this->middleware('auth')->except('index', 'show');
  }

The TaskController class opens up its two methods (index and show) only for guests or the public. To operate other methods, you need to be an authenticated user, and then you can also apply authorization and all the other related middleware actions.

In the “Authentication, Authorization, and Middleware” Chapter 8, I will discuss the methodologies behind the TaskController class. Until then, know that through your Controller class you can control your entire application. The greatness of Laravel is that it also gives you ample chances to control your application through other parts, such as your route file, view page, and the model.

Now, if you type http://localhost:8000/tasks in your browser, you will see the page in Figure 3-2.
../images/435350_2_En_3_Chapter/435350_2_En_3_Fig2_HTML.jpg
Figure 3-2

Showing all tasks

In the next section, you will see how resourceful controllers come to your rescue while you try to maintain a separation of concerns.

And if you click the second task, you will see the view page shown in Figure 3-3.
../images/435350_2_En_3_Chapter/435350_2_En_3_Fig3_HTML.jpg
Figure 3-3

The third task

Now go to http://localhost:8000/tasks/3, which is the third task. In the TaskController class, the method is show.

Remember this part of the file TaskController.php :
//code 3.13
public function show($id)
    {
        //
        $task = Task::findOrFail($id);
        return view('tasks.show', compact('task'));
    }
This actually returns show.blade.php belonging to the resources/views/tasks folder, and the code snippet I have used there looks like this:
//code 3.14
// resources/views/tasks/show.blade.php
<div class="card-body">
                    {{ $task->title }}
                </div>
                <div class="card-body">
                    {{ $task->body }}
                </div>

I will discuss this part in a moment, so please keep reading.

Models Act As Resources

I would like to mention one thing: the TaskController class manages the task resource in such a way that you can view the index.blade.php and show.blade.php pages without being authenticated. However, you can do that in other parts of the same resource.

Suppose you want to type this URI: http://localhost:8000/tasks/create. This will take you to the login page. See Figure 3-4.
../images/435350_2_En_3_Chapter/435350_2_En_3_Fig4_HTML.jpg
Figure 3-4

The login page

Why does this happen?

Remember this part of TaskController.php:
//code 3.15
public function create()
    {
        //
        if(Auth::user()->is_admin == 1){
            return view('tasks.create');
        }
        else {
          return redirect('home');
        }
    }

This clearly states that if the user is not admin , they cannot view this page. Otherwise, it redirects the user to the home page, which again redirects back to the login page.

I hope that you can now follow the logic behind Laravel’s routes, controller, model, and view mechanism. In the route lists, you can see how these components are related to each other. For each request, whether that be GET or POST, Laravel handles it nicely and relates it to the respective URI. Then that URI fires up the respective RESTful Controller method, and that takes you to the respective view page.

In the next section, you will see how the RESTful or resourceful controller encapsulates those URI requests in a single line.

Resourceful Controllers

With a single line of code, how can you handle a typical CRUD route to a controller? Laravel’s resource routing is the answer. You want to store every task in your database. You want to edit and update every task. You want to create a controller that handles all HTTP requests for tasks stored by your application.

You have already created the resource TaskController that way, and you have seen how it contains a method for each of the available resource operations. Next, you have registered a route to that controller, as shown here:
    Route::resource('tasks', 'TaskController');

Now, this single route declaration creates multiple routes to handle a variety of actions on the resource. If you open the app/HTTP/Controllers/TaskController.php file, you will find that each of these actions has related notes informing you of the HTTP verbs and URIs they handle.

Let’s see one example of the index method :
//code 3.16
// app/HTTP/Controllers/TaskController.php
/**
     * Display a listing of the resource.
     *
     * @return IlluminateHttpResponse
     */
    public function index()
    {
        $tasks = Task::get();
        return view('tasks.index', compact('tasks'));
    }

This clearly states “Display a listing of the resource.” At the same time, if you watch the route listing (shown next), you will find for the action AppHttpControllersTaskController@index that the name is tasks.index (this means the index.blade.php file belonging to the tasks folder). The method is GET, and the URI is tasks. This means if you type the URI http://localhost:8000/tasks, you will view all the tasks.

You can write all actions handled by the resource TaskController in one place in this way:
//code 3.17
Method    | URI                   | Action       | Route Name
----------|-----------------------|--------------|---------------------
GET       | 'tasks'               | index        | tasks.index
GET       | 'tasks/create'        | create       | tasks.create
POST      | 'tasks'               | store        | tasks.store
GET       | 'tasks/{task}'        | show         | tasks.show
GET       | 'tasks/{task}/edit'   | edit         | tasks.edit
PUT/PATCH | 'tasks/{task}'        | update       | tasks.update
DELETE    | 'tasks/{task}'        | destroy      | tasks.destroy

The Importance of the Resourceful Controller

Creating controllers in Laravel is simple. In an MVC pattern, controllers play a vital role, and defining all your request handling logic as an anonymous function in a route file is not a viable solution for a big application. So, you will always use controllers as a transport medium. The main advantage of a controller is that it can group all the request handling into a single class, and that class can be stored in the app/HTTP/Controllers directory .

Another advanced feature is that you can register many resource controllers at once by passing an array to the resources method. It looks like this:
    Route::resources([
        'myfiles' => 'MyController',
        'moreactions' => 'MoreController'
    ]);

A resourceful controller uses many types of HTTP verbs at the same time, such as GET, POST, PUT/PATCH, and DELETE. By using the GET verb, you can access four action methods in the controller; they are index, create, show, and edit. The action methods in the controller handle the route names of the same name; for example, the index action would handle a URI like /myfiles and a route name of myfiles.index. The create and edit actions only show web forms, so the GET verb is perfect for them.

You need a POST verb or method for the store action because you are sending data to the app, and behind the scenes, the Laravel service container (I will discuss this later in detail) takes the trouble to go through the model to insert new data in the related database table. The URI remains the same as index, like /myfiles, but the action method changes to store, and the route name also changes to myfiles.store. The HTTP verb PUT/PATCH is used for updating only a single record. Therefore, the URI changes to /myfiles/{myfile}, the action method changes to update, and the Route name changes to myfiles.update.

How to Supplement the Resource Controller

Sometimes you may want to add routes to a resource controller. A resource controller always handles a default set of resource routes; however, you may want a few more like this:
//code 3.18
Route::get('tasks/important', 'TaskController@important');
Of course, your resource controller will never create an extra method like this. You need to add it manually. However, you need to register this route before the resource route. Otherwise, the resource route will take precedence. In the routes/web.php file, you should write these lines of code:
//code 3.19
Route::get('tasks/important', 'TaskController@important');
Route::resource('tasks', 'TaskController');

However, you should keep your controller focused, and to do that, my suggestion is that it is better to maintain several small controllers so you don’t have to juggle with the position in your route file.

Getting User Input and Dependency Injection

The Laravel service container is used to resolve all Laravel controllers. This means that when you create a resource controller, method injection normally occurs. How does this work?

It’s simple. Just take a look at these lines of code in your TaskController store method:
//code 3.20
    public function store(Request $request)
    {
        if(Auth::user()->is_admin == 1){
          $post = new Task;          $post->title = $request->input('title');
          $post->body = $request->input('body');
          $post->save();
          if($post){
             return redirect('tasks');
          }
        }
    }
The $request object from IlluminateHttpRequest has automatically been injected and resolved by Laravel’s service container. Behind the scenes, a form is sending data, and you can get the following code as a result:
$post->title = $request→input('title');
When you are going to edit any task item, the same thing takes place in the update method.
//code 3.21
    public function update(Request $request, $id)
    {
        if(Auth::user()->is_admin == 1){
            $post = Task::findOrFail($id);
            $post->title = $request->input('title');
            $post->body = $request->input('body');
            $post->save();
            if($post){
             return redirect('tasks');
            }
        }
    }

Here, you may ask, how does Laravel know the wildcard reference or input variable $id along with the Request $request object? This happens through the Reflection class that Laravel uses to guess what you are type hinting, and this is called method injection .

Basically, you could have passed the parameter’s Model object as ' instead of $id; however, since through the edit form you have passed $id, Laravel resolves the dependencies and injects it into the controller instance in place of '.

The position of the $id along with the Request $request object is interchangeable. Laravel is smart enough to read the wildcard entry and the $request object here. So, you can type hint the dependencies on your controller methods. The most common use case is the injection of the IlluminateHttpRequest instance.

If your controller method expects input from a route parameter, as happens in the update case where you want to catch the $id of the item you want to edit, behind the resource controller, you have a route like this:
Route::put('task/{id}', 'TaskController@update');
You can also type hint any dependencies your controller may need in the constructor. The declared dependencies will automatically be resolved and injected into the controller instance. Suppose you have a user repository in the app/Repositories folder like this:
//code 3.22
//app/Repositories/DBUserRepository.php
<?php namespace RepositoryDB;
use RepositoryInterfaceUserRepositoryInterface as UserRepositoryInterface;
use AppUser;
use IlluminateHttpRequest;
class DBUserRepository implements UserRepositoryInterface {
    public function all() {
        return User::all();
    }
}
You also have the app/Repositories/Interfaces folder, where you have your respective interface that looks like this:
//code 3.23
//app/Repositories/Interfaces/UserRepositoryInterface.php
<?php namespace RepositoryInterface;
 interface UserRepositoryInterface {
     public function all();
}
Now you can inject your dependencies into your UserController constructor quite easily. I have type hinted the contract (here UserRepositoryInterface), and the Laravel container has resolved it successfully.
//code 3.24
//app/HTTP/Controllers/UserController.php
class UserController extends Controller {
    public $users;
    public function __construct(DBUserRepository $users) {
        $this->users = $users;
    }
...//code continues
}

The instance of DBUserRepository always provides better testability.

How a Blade Template Works with Controllers and Models

Blade is a simple yet powerful template engine. It reduces the workload of the front-end staff drastically. With Blade templates, you can also use PHP code. Besides, it has its own PHP syntax, which is extremely easy to use.

The advantage of Blade views is that they come with automatic caching. All Blade view pages are compiled into plain PHP code and cached until you modify them. This means zero overhead for the application.

You can create any Blade view page with a .blade.php extension, and they should be stored inside the resources/views folder. For a large application, you may create separate folders for each resource and keep your view pages inside that. Likewise, I have kept my Task resource view pages inside the resources/views/tasks folder.

Two basic benefits of Blade are template inheritance and sections.

For the Task resource, you are using the default resources/views/layouts/app.blade.php file here. So, the resources/views/tasks/index.blade.php file is a simple view page that outputs the tasks.
//code 3.25
//resources/views/tasks/index.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Task Page</div>
                <div class="card-body">
                    @foreach($tasks as $task)
                    <a href="/tasks/{{ $task->id }}">
                        {{ $task->title }}
                    </a>
                    <p></p>
                    @endforeach
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

As you see, you can easily connect your view page to the master layout page by writing the following on the top of the page: @extends('layouts.app'). In between @section('content') and @endsection, you insert the content part. Basically, you are following the DOM object model for displaying the HTML page. It starts on the top and flows down to the end.

The master layout Blade page should have the header and the footer. If there is any fixed sidebar, according to the Bootstrap theme, you can include that also. If you create a simple master layout Blade page, it will look like the app.blade.php file in your resources/views/layouts folder, as shown here:
//code 3.26
    <html>
        <head>
            <title>App Name - @yield('title')</title>
        </head>
        <body>
            <div class="container">
                @yield('content')
            </div>
        </body>
    </html>
The @yield('content') part uses your index.blade.php page content. In the default app.blade.php page, that part is included like this:
<main class="py-4">
            @yield('content')
        </main>

But I have overwritten the default app.blade.php page to make it simple to understand. When Laravel installs, it comes with a default app.blade.php view page in the resources/views/layouts folder.

The @section and @yield directives are there with the typical HTML markup. The @section directive defines a section of content. Here, the @yield directive is used to display the contents of a given section.

Security in Blade

In any Blade view page, you usually get the data inside curly braces: {{ $data->body }}'. These statements are automatically sent through PHP’s htmlspecialchars function to avoid XSS attacks so that the data is escaped.

If you do not want to escape data, then use this syntax: {!! $data->body !!}. But, be careful about the user’s input. It is always a good practice to escape data supplied by users. The user’s input data should be displayed using double curly braces: {{ $user->data }}'.

Authentication Through Blade

You can check whether the user is an administrator in the Blade view page, as shown here:
//code 3.27
    @foreach ($users as $user)
        @if ($user->admin == 1)
            @continue
        @endif
        <li>{{ $user->name }}</li>
        @if ($user->number == 1)
            @break
        @endif
    @endforeach
You can also check whether the user is a registered member with this simple method:
//code 3.28
    @auth
        // The user is authenticated...
    @endauth
    @guest
        // The user is not authenticated...
    @endguest
In Chapter 8, I will discuss the guard; however, in the Blade view page, you can use it directly like this:
//code 3.29
    @auth('admin')
        // The user is authenticated...
    @endauth
    @guest('admin')
        // The user is not authenticated...
    @endguest

Control Structures in Blade

You have already seen how you can manage looping through a Blade template; you can put control structures in any Blade view page like this:
//code 3.30
@if (count($users) === 1)
        I have one user!
    @elseif (count($users) > 1)
        I have multiple users!
    @else
        I don't have any users!
    @endif
Take a look at the following example where the @unless directive makes authentication much simpler:
//code 3.31
    @unless (Auth::check())
        You are not signed in.
    @endunless

Other Advantages of Blade Templates

You can also use the PHP isset function in a more convenient way like this:
//code 3.32
    @isset($images)
        // $images is defined and is not null...
    @endisset
    @empty($images)
        // $images is 'empty'...
    @endempty
You have already seen how you can use the foreach loop for getting records straight out of the database tables; in addition, you can restrict the number of records in the view page instead of doing this inside the controller. You can even choose which records to show.
//code 3.33
@foreach ($users as $user)
      @if ($user->id == 1)
          @continue
      @endif
      <li>{{ $user->name }}</li>
      @if ($user->id == 3)
          @break
      @endif
  @endforeach
You have four registered users. The output is as follows:
//output of code 3.34
•    ss
•    admin

In this case, when the loop finds that the ID is 1, it continues. After that, when the code reaches the second user, the loop stops and spits out the first two users’ names, and after that it stops and breaks out from the loop when it finds the third user.

You can manipulate your database records by managing the control structures in the Blade view pages. And in such cases, Laravel allows you to do that without touching the models and controllers. This is a big advantage of using Laravel.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.120.204