这实际上并不太难,但它确实需要一些设置才能使中间件能够检测到正在加载的资源。这是通过使用Route-Model Binding完成的
示例资源路由:
Route::group(['middleware' => 'BelongsToAccount'], function() {
Route::resource('asset', 'AssetController');
Route::resource('liability', 'LiabilityController');
});
现在,我们需要绑定资源,RouteServiceProvider
以便我们的路由加载资源:
/**
* Define your route model bindings, pattern filters, etc.
*
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function boot(Router $router)
{
parent::boot($router);
// bound models
$router->model('asset', 'App\Asset');
$router->model('liability', 'App\Liability');
}
现在转到中间件的handle
方法并转储$request->route()->parameters();
。您应该会看到参数列表中列出的资源。使用请求中可用的资源实例,最后一步是在中间件中检查并验证它:
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Routing\Middleware;
class BelongsToAccount implements Middleware {
/**
* The Guard implementation.
*
* @var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* @param Guard $auth
* @return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// get the resource from the route
$resource = $this->getResource($request);
if (!empty($resource))
{
if ($this->auth->user()->accountId == $resource->accountId)
{
return $next($request);
}
}
}
/**
* Get resource from route if it exists
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function getResource($request)
{
foreach ($request->route()->parameters() as $param)
{
if ($param instanceof Model) return $param;
}
return null;
}
}
上面的代码不是即插即用的,您可能需要准确更改accountId
从当前登录用户获取值的方式等。但是这里发生的事情的要点是添加了一个额外的方法来查找实例的一个Eloquent\Model
。找到后,它会返回此资源以供中间件使用,并假定该资源已经绑定了一个 accountId。
如果您想要更精细的控制,我建议将中间件移至控制器__construct
,以更具体地调整它所处理的控制器操作。不过,您也可以在路由文件中完成此操作。
希望这可以帮助!