我在Laravel 5.1中有几个由模型表示的资源。模型都有account_id和user_id。 user_account的数据透视表表示帐户和用户之间的关系。
我在routes.php中有路由,它们是资源控制器,例如route.asset。
我希望为所有这些控制器创建一个中间件,我可以在=>之前完成[' belongstoaccount']
在那个中间件中它应该检查:
用户属于account.asset中的帐户(我目前在控制器中使用 - > contains()。)
资产的account_id与account-> id匹配。
我想为所有这些资产制作一个中间件。这甚至可能吗?我应该查询$请求这些信息吗?
感谢您提供任何指导,
约什
答案 0 :(得分:1)
这实际上并不太难,但它确实需要为中间件设置一些能够检测正在加载哪个资源的设置。这是通过使用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
,以更具体地调整它所使用的控制器动作。不过,您也可以在路径文件中完成此操作。
希望这有帮助!