简体   繁体   中英

Models, Resource Controllers and Middleware in Laravel 5.1

I have several resources in Laravel 5.1 that are represented by models. The models all have account_id and user_id. There is a pivot table of user_account that represents the relationship between accounts and users.

I have my routes in routes.php that are resource controllers such as route.asset.

I am looking to create one Middleware for all of these controllers such I can do before => ['belongstoaccount']

And in that middleware it should check:

User belongs to the account in account.asset (I currently use ->contains() in the controllers.)

The account_id of the asset matches the account->id.

I want to make one middleware for all these assets. Is this even possible? Should I be looking in $request for this information?

Thank you for any guidance,

Josh

This is actually not too difficult, but it does require a bit of setup for the middleware to be able to detect which resource is being loaded. This is accomplished by using Route-Model Binding

Example resource routes:

Route::group(['middleware' => 'BelongsToAccount'], function() {
    Route::resource('asset', 'AssetController');
    Route::resource('liability', 'LiabilityController');
});

Now, we need to bind the resources in RouteServiceProvider so our routes will load the resources:

   /**
     * 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');
    }

Now go to the middleware's handle method and dump $request->route()->parameters(); . You should see the resource listed in the parameter list. With the instance of the resource available in the request, the last step is to check for and validate against it in the middleware:

<?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;
    }
}

This code above won't be plug and play, you may need to change exactly how you get the accountId value from your currently logged in user, etc. But the gist of what's going on here is an additional method was added to look for an instance of an Eloquent\\Model . Once it's found, it returns this resource to be used by the middleware and assumes that the resource has an accountId already bound to it.

If you want a more fine control, I'd suggest moving the middleware to the controller's __construct to more specifically tune which controller actions it works on. You can accomplish this in the routes file as well, though.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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