This article will continue where we left off in out Part 2 of the Laravel tutorial series.

Laravel is a powerful MVC PHP framework, designed for developers who need a simple and elegant toolkit to create full-featured web applications. Laravel was created by Taylor Otwell. This is a brief tutorial that explains the basics of Laravel framework.

In this article, we will have a look at key features available in Laravel, such as Middlewares, Controller design, Request flow and Cookies management in the framework. So, let’s dive straight into the framework.

Middleware in Laravel

As the name suggest, middleware in Laravel acts like a filter for HTTP request that comes for our application. For example, framework includes a middleware system that will verify if the user making a request to our app is authenticated. If he isn’t authenticated to make the request, the middleware will redirect the user to a different screen, like a login screen. However, he indeed is authenticated, the middleware will allow the request to proceed further into the application.

Now, we might want to add our own code into a middleware and that is possible completely in Laravel. Additional middleware can be added to perform a variety of tasks besides authentication. A logging middleware might log all incoming requests to our application with other information like time, URI etc.

Middleware can be created by executing the following command:

php artisan make:middleware <name>

Like, let us define a middleware to allow a user to enter a page only if the user is premium, we can do it by following a command and code snippet:

php artisan make:middleware checkPremium <?php namespace App\Http\Middleware; use Closure; class CheckPremium { /** * Handle an incoming request. */ public function handle($request, Closure $next) { if ($request->premium == 1) { return redirect('home'); } return $next($request); } }

Before & After Middleware

Whether a middleware runs before or after a request depends on the middleware itself. For example, let’s define a middleware that runs before a request:

<?php namespace App\Http\Middleware; use Closure; class BeforeMiddleware { public function handle($request, Closure $next) { // Perform action return $next($request); } }

However, this middleware would perform its task after the request is handled by the application:

<?php namespace App\Http\Middleware; use Closure; class AfterMiddleware { public function handle($request, Closure $next) { $response = $next($request); // Perform action return $response; } }

Register Middleware

We need to register a middleware before using it. There are two types of Middlewares in Laravel:

Global Middleware

Route Middleware

The Global Middleware will run on every HTTP request of the application, whereas the Route Middleware will be assigned to a specific route.

>>> The middleware can be registered at app/Http/Kernel.php.

This file contains two properties $middleware and $routeMiddleware. $middleware property is used to register Global Middleware and $routeMiddleware property is used to register route specific middleware.

To register the global middleware, list the class at the end of $middleware property.

protected $middleware = [ \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, ];

To register the route specific middleware, add the key and value to $routeMiddleware property.

protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, ];

Middleware Parameters

We can also pass parameters to a Middleware. For example, if our app has different roles like user, admin, super admin etc. and we want to authenticate the request based on role, this can be achieved by passing parameters to the middleware. The middleware that we create contains the following function and we can pass our custom argument after the $next argument.

public function handle($request, Closure $next) { return $next($request); }

Example

Create RoleMiddleware by executing the following command −

php artisan make:middleware RoleMiddleware





Let’s add some code snippet to our newly created RoleMiddleware in app/Http/Middleware/RoleMiddleware.php :

<?php namespace App\Http\Middleware; use Closure; class RoleMiddleware { public function handle($request, Closure $next, $role) { echo "Role: ".$role; return $next($request); } }

Next, register the RoleMiddleware in the file app\Http\Kernel.php file. Add the following snippet:

protected $routeMiddleware = [ … 'Role' => \App\Http\Middleware\RoleMiddleware::class, ];







Execute the following command to create a TestController:

php artisan make:controller TestController --plain





After successful execution, you will receive the following output −

Controller created successfully

Copy the following code to our newly created app/Http/TestController.php file:

app/Http/TestController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Http\Controllers\Controller; class TestController extends Controller { public function index(){ echo "<br>Test Controller."; } }

Add the following line of code in app/Http/routes.php file.

app/Http/routes.php Route::get('role',[ 'middleware' => 'Role:editor', 'uses' => 'TestController@index', ]);







Now, visit the following URL to test the Middleware with parameters

http://localhost:8000/role

Step 10 − The output will appear as shown:

Role: editor

Test Controller.

Controllers

Let’s begin with a basic controller class. 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, which may be used to attach middleware to controller actions:

<?php namespace App\Http\Controllers; use App\User; use App\Http\Controllers\Controller; class UserController extends Controller { /** * Show the profile for the given user. */ public function show($id) { return view('user.profile', ['user' => User::findOrFail($id)]); } }

We can define a route to this controller action like so:

Route::get('user/{id}', 'UserController@show');

Now, when a request is made to the specified route URI, the show method on the UserController.class will be executed. Of course, the route parameters will also be passed to the method.

Controllers are not required to extend a base class. However, we will not have access to convenience features such as the middleware, validate, and dispatch methods.

Controllers & Namespaces

It is very important to note that we did not need to specify the full controller namespace when defining the controller route. Since the RouteServiceProvider loads our route files within a route group that contains the namespace, we only specified the portion of the class name that comes after the App\Http\Controllers portion of the namespace.

If you choose to nest your controllers deeper into the App\Http\Controllers directory, we can simply use the specific class name relative to the App\Http\Controllers root namespace. So, if the full controller class is App\Http\Controllers\Photos\AdminController, we should register routes to the controller like so:

Route::get('foo', 'Photos\AdminController@method');

Single Action Controllers

If we would like to define a controller that only handles a single action, you may place a single __invoke method on the controller:

<?php namespace App\Http\Controllers; use App\User; use App\Http\Controllers\Controller; class ShowProfile extends Controller { /** * Show the profile for the given user. */ public function __invoke($id) { return view('user.profile', ['user' => User::findOrFail($id)]); } }

When registering routes for single action controllers, you do not need to specify a method:

Route::get('user/{id}', 'ShowProfile');

Controller Middleware

Middleware may be assigned to the controller's routes in your route files:

Route::get('profile', 'UserController@show')->middleware('auth');

However, it is more convenient to specify middleware within our controller's constructor. Using the middleware method in our controller's constructor, we may easily assign middleware to the controller's action. We may even restrict the middleware to only certain methods on the controller class:

class UserController extends Controller { public function __construct() { $this->middleware('auth'); $this->middleware('log')->only('index'); $this->middleware('subscribed')->except('store'); } }

Controllers also allow you to register middleware using a Closure. This provides a convenient way to define a middleware for a single controller without defining an entire middleware class:

$this->middleware(function ($request, $next) { // ... return $next($request); });

We may assign middleware to a subset of controller actions; however, it may indicate your controller is growing too large. Instead, consider breaking your controller into multiple, smaller controllers.

Accessing The Request

Now, let’s see how to access request and the other information contained in it like path and parameters. To obtain an instance of the current HTTP request via dependency injection, we can type-hint the Illuminate\Http\Request class on our controller method. The incoming request instance will automatically be injected by the service container:

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller { public function store(Request $request) { $name = $request->input('name'); // } }

Dependency Injection & Route Parameters

If your controller method is also expecting input from a route parameter you should list your route parameters after your other dependencies. For example, if your route is defined like so:

Route::put('user/{id}', 'UserController@update');

We may still type-hint the Illuminate\Http\Request and access your route parameter id by defining your controller method as follows:

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller { public function update(Request $request, $id) { // } }

Accessing The Request Via Route Closures

We may also type-hint the Illuminate\Http\Request class on a route Closure. The service container will automatically inject the incoming request into the Closure when it is executed:

use Illuminate\Http\Request; Route::get('/', function (Request $request) { // });

Retrieving The Request URL

To retrieve the full URL for the incoming request you may use the url or fullUrl methods. The url method will return the URL without the query string, while the fullUrl method includes the query string:

// Without Query String... $url = $request->url(); // With Query String... $url = $request->fullUrl();

Retrieving The Request Method

The method will return the HTTP verb for the request. You may use the isMethod to verify that the HTTP verb matches a given string:

$method = $request->method(); if ($request->isMethod('post')) { // }

Cookies in Laravel

Cookie can be created by global cookie helper of Laravel. It is an instance of Symfony\Component\HttpFoundation\Cookie. The cookie can be attached to the response using the withCookie() method.

Create a response instance of Illuminate\Http\Response class to call the withCookie() method. Cookies generated by Laravel are encrypted and signed and it can’t be modified or read by the client.

Here is a sample code with explanation.

//Create a response instance $response = new Illuminate\Http\Response('Hello World'); //Call the withCookie() method with the response method $response->withCookie(cookie('name', 'value', $minutes)); //return the response return $response;

Cookie() method will take 3 arguments.

First argument is the name of the cookie.

Second argument is the value of the cookie.

The third argument is the duration of the cookie after which the cookie will get deleted automatically.

Cookie can be set forever by using the forever method as shown in the below code.

$response->withCookie(cookie()->forever('name', 'value'));

Reading a Cookie

Once we set the cookie, we can retrieve the cookie by cookie() method. This cookie() method will take only one argument which will be the name of the cookie. The cookie method can be called by using the instance of Illuminate\Http\Request. Let’s see sample code snippet:

//'name' is the name of the cookie to retrieve the value of $value = $request->cookie('name');

Conclusion

In this article, we continued our journey to explain key features offered by Laravel like Middlewares, Controller design, Request flow and Cookies management in the framework.

There is a lot more to come which we will read in the Part 4 of our Laravel tutorial series like Response, Views, Redirections, Working With Database and Errors and Logging in Laravel.