Laravel Tutorial - Middleware and controllers (Part 3)
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.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment