Laravel - 在控制器构造之后调用的中间件
Laravel - Midlleware called after controller construct
编辑:更好的例子
我在使用在 SectionsController 构造函数之后调用的 checkauth 控制器时遇到问题 - 这是扩展的 ReportController,我不知道为什么它会这样工作。
我尝试在 SectionController 构造的开头添加中间件,例如 $this->middleware('checkauth'); 但也不起作用。
中间件
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
class CheckAuth
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!Auth::check())
{
return redirect('/admin/login')->withErrors(['message' => 'You need to login before proceeding']);
}
return $next($request);
}
}
部分控制器
<?php
namespace App\Http\Controllers\RMReport;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\View;
use App\Http\Controllers\Controller;
use Illuminate\Http\UploadedFile;
class SectionsController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
protected $user;
public function __construct(){
$this->middleware('checkauth');
dump("SECTIONSCONTROLLER: ");
dump(\Auth::check());
//PROBLEM HERE - \Auth::Check is false , \Auth::user is null
$this->user = \Auth::user();
if( !$this->user->can('something') ) return redirect()->route('someroute');
}
}
报表控制器
<?php
namespace App\Http\Controllers\RMReport\Form;
use App\Http\Controllers\RMReport\SectionsController;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class ReportController extends SectionsController
{
public function form(){
if( $this->user->status != 'Active'){
return something;
}
return another something;
}
}
来自 route:list
的输出
GET|HEAD | admin/remote-report/{id?} | rm.report | App\Http\Controllers\RMReport\Form\ReportController@form | web,checkauth,checkownerRMreport |
POST | admin/remote-report/{id?} | rm.report | App\Http\Controllers\RMReport\Form\ReportController@store | web,checkauth,checkownerRMreport |
调用 GET 输出
"SECTIONSCONTROLLER: "
false
"CHECKAUTH:"
true
了解 Laravel
生命周期和对象生命周期很重要。创建新对象时,将先调用构造函数。当 new SectionsController() 的动作发生时,它会立即触发构造函数,因为构造函数调用中间件,它无法知道它应该运行之前。
这意味着在请求生命周期中,控制器构造函数必须在中间件之前。幸运的是,这个问题已经解决了,如果你在构造函数中对依赖于中间件的逻辑使用回调,你将避免这个问题。
$this->middleware(function ($request, $next) {
dump("SECTIONSCONTROLLER: ");
dump(\Auth::check());
});
编辑
您可以将 Laravel
中间件用于策略,而不是在构造函数中执行所有错误的操作。这需要您使用 Authorize 中间件,该中间件按标准启用。
$this->middleware('can:something');
编辑:更好的例子
我在使用在 SectionsController 构造函数之后调用的 checkauth 控制器时遇到问题 - 这是扩展的 ReportController,我不知道为什么它会这样工作。 我尝试在 SectionController 构造的开头添加中间件,例如 $this->middleware('checkauth'); 但也不起作用。
中间件
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
class CheckAuth
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!Auth::check())
{
return redirect('/admin/login')->withErrors(['message' => 'You need to login before proceeding']);
}
return $next($request);
}
}
部分控制器
<?php
namespace App\Http\Controllers\RMReport;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\View;
use App\Http\Controllers\Controller;
use Illuminate\Http\UploadedFile;
class SectionsController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
protected $user;
public function __construct(){
$this->middleware('checkauth');
dump("SECTIONSCONTROLLER: ");
dump(\Auth::check());
//PROBLEM HERE - \Auth::Check is false , \Auth::user is null
$this->user = \Auth::user();
if( !$this->user->can('something') ) return redirect()->route('someroute');
}
}
报表控制器
<?php
namespace App\Http\Controllers\RMReport\Form;
use App\Http\Controllers\RMReport\SectionsController;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class ReportController extends SectionsController
{
public function form(){
if( $this->user->status != 'Active'){
return something;
}
return another something;
}
}
来自 route:list
的输出GET|HEAD | admin/remote-report/{id?} | rm.report | App\Http\Controllers\RMReport\Form\ReportController@form | web,checkauth,checkownerRMreport |
POST | admin/remote-report/{id?} | rm.report | App\Http\Controllers\RMReport\Form\ReportController@store | web,checkauth,checkownerRMreport |
调用 GET 输出
"SECTIONSCONTROLLER: "
false
"CHECKAUTH:"
true
了解 Laravel
生命周期和对象生命周期很重要。创建新对象时,将先调用构造函数。当 new SectionsController() 的动作发生时,它会立即触发构造函数,因为构造函数调用中间件,它无法知道它应该运行之前。
这意味着在请求生命周期中,控制器构造函数必须在中间件之前。幸运的是,这个问题已经解决了,如果你在构造函数中对依赖于中间件的逻辑使用回调,你将避免这个问题。
$this->middleware(function ($request, $next) {
dump("SECTIONSCONTROLLER: ");
dump(\Auth::check());
});
编辑
您可以将 Laravel
中间件用于策略,而不是在构造函数中执行所有错误的操作。这需要您使用 Authorize 中间件,该中间件按标准启用。
$this->middleware('can:something');