繁体   English   中英

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

[英]Models, Resource Controllers and Middleware in Laravel 5.1

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

我在route.php中有我的路由,这些路由是资源控制器,例如route.asset。

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

在该中间件中,应检查:

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

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

我想为所有这些资产制作一个中间件。 这有可能吗? 我应该在$ request中寻找此信息吗?

感谢您的指导,

乔希

这实际上并不算困难,但是中间件确实需要一些设置才能检测到正在加载哪个资源。 这是通过使用路由模型绑定来完成的

资源路由示例:

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以更具体地调整其对哪个控制器动作进行调整。 不过,您也可以在路由文件中完成此操作。

希望这可以帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM