Laravel middleware terminate not called when using constructor version

Viewed 5208

Laravel version: 5.1.46

routes.php

Route::get('/rocha', 'RochaController@index');

Kernel.php

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

RochaController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

class RochaController extends Controller
{

    public function __construct() {
        $this->middleware('Role');
    }
    public function index() {
        echo '<br>Hi I am index';
    }
}

RochaMiddleware.php

namespace App\Http\Middleware;
use Closure;

class RoleMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        echo '<br>Hi I am middleware';
        return $next($request);
    }


    public function terminate($request, $response) {
        echo '<br>Shtting down...';
    }
}

Result:

Hi I am middleware
Hi I am index

When I use middleware inside the controller via it's constructor $this->middleware('Role') the terminate() function does not get called. When I switch the code taking out the constructor in the controller and change the route to the following the terminate() function gets called:

Route::get('/rocha', [
    'middleware' => 'Role',
    'uses' => 'RochaController@index'
]);

Result:

Hi I am middleware
Hi I am index
Shtting down...

Why does the constructor version ($this->middleware('Role')) prevent the terminate() function from being called?

Why does the route version work and the terminate() function is called as opposed to the above?

1 Answers

If you define a terminate method on your middleware, it will automatically be called after the response is ready to be sent to the browser.

from terminable-middleware

I think you misunderstand the usage of terminate method. Laravel actually call the terminate method, but the browser will not show the output of terminate. Because the response has been sent to browsers.

You can use this terminate method to test whether the call is successful.

public function terminate($request, $response)
{
    file_put_contents(__DIR__ . '/1.txt', 'hello terminate');
}

By the way, I'm test your code, it always output:

Hi I am middleware
Hi I am index

I also wonder why you can get Shtting down...

The above is all I know about this. Sorry for my bad english.

Related