Laravel 5.1中的模型,资源控制器和中间件

时间:2015-12-28 20:46:17

标签: php laravel-5.1 laravel-middleware

我在Laravel 5.1中有几个由模型表示的资源。模型都有account_id和user_id。 user_account的数据透视表表示帐户和用户之间的关系。

我在routes.php中有路由,它们是资源控制器,例如route.asset。

我希望为所有这些控制器创建一个中间件,我可以在=>之前完成[' belongstoaccount']

在那个中间件中它应该检查:

用户属于account.asset中的帐户(我目前在控制器中使用 - > contains()。)

资产的account_id与account-> id匹配。

我想为所有这些资产制作一个中间件。这甚至可能吗?我应该查询$请求这些信息吗?

感谢您提供任何指导,

约什

1 个答案:

答案 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,以更具体地调整它所使用的控制器动作。不过,您也可以在路径文件中完成此操作。

希望这有帮助!