Laravel - 设置默认路由前缀

Laravel - Setting a default route prefix

我想根据用户公司为我的所有路由设置默认路由前缀,例如

Route::group(['prefix' => '/{company}'], function() {
    Route::get('/', 'CompaniesController@index')->name('company.index');

});

有没有什么方法可以通过中间件等设置这个值,这样我就不必在每种方法上都做这样的事情,用户只能访问他们自己的公司。

public function index(Company $company)
    {
        if(auth()->user()->company == $company) {
            return $company;
        }
        abort(404);
    }

使用 Laravel 6.x

你可以像这样在路由级别使用中间件:

1) 构建您的中间件:

<?php

namespace App\Http\Middleware;

use App\Models\Company;
use Closure;

class CheckUserCompany
{
    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     *
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if(auth()->user()->company == $request->company) {
            return $next(;
        }
         abort(404);
     }
}

您可能不需要 Company 模型,因为您正在从路由变量中获取公司价值。

2) 在 App\Http\Kernel.php:

中注册你的中间件
protected $routeMiddleware = [
'company.check' = \App\Http\Middleware\CheckUserCompany::class
 ];

3) 那么你的路线应该是这样的:

Route::group(['prefix' => '/{company}', 'middleware' => 'company.check'], function() {
    Route::get('/', 'CompaniesController@index')->name('company.index');

});
  1. 用命令php artisan make:middleware CompanyMiddleware制作一个中间件,在Kernel.php中为其设置名称(我将其命名为"company")并处理 公司中间件中的方法必须是这样的:

    public function handle($request, Closure $next) {
      $request->attributes->add(['company' => auth()->user()->company]);
      return $next($request);
    }
    

    在 kernel.php 中:

    'company' => CompanyMiddleware::class,
    
    1. 在路由中应用中间件:

      Route::group(['prefix' => '/{company}', 'middleware' => 'company'], function(){
        Route::get('/', 'CompaniesController@index')->name('company.index');
      });
      
    2. 在为其定义公司中间件的路由方法中获取 $company:

      public function index() {
        $company = request()->company;
      }
      

希望对你有用。

为此您不需要任何自定义中间件,您可以使用策略和 laravel 的内置 can 中间件来实现。

在您的情况下,它将类似于以下内容:

// app/Policies/CompanyPolicy.php
class PostPolicy
{
    public function view(User $user, Company $company)
    {
        return $user->company->getKey() === $company->getKey();
    }
}


// web.php
Route::group(['prefix' => '/{company}'], function() {
    Route::get('/', 'CompaniesController@index')->name('company.index');

})->middleware('can:view,company');


// Controller
public function index(Company $company)
{

    return 'magic';
}

有关这方面的更多信息,您可以观看以下文档:
https://laravel.com/docs/6.x/authorization#creating-policies
https://laravel.com/docs/6.x/authorization#via-middleware

如果你问的是在 中间件 class 中注册路由,那是不可能的,因为中间件本身是应用在已经注册的路线。


但是,您可以使用 route groups 并应用重定向到经过身份验证的用户的 "company" 的中间件。

routes.php

<?php

use App\Http\Middleware\RedirectToCompany;

// Use the auth middleware before the RedirectToCompany middleware to make sure users are authenticated

Route::middleware('auth', RedirectToCompany::class)->name('company.')->prefix('/{company}')->group(function () {
    Route::get('/', ....)->name('index');
    //Your routes here
})->where('company', '(google|microsoft|yahoo)'); //Here i supposed that your company is not really bound, you can omit this

Note: You are also able to register multiple route groups inside of the presented route group if your companies have different routes.

RedirectToCompany.php

<?php

namespace App\Http\Middleware;

use Closure;

public function handle($request, Closure $next)
{
    if ($user->company != $request->route('company')) {
        return redirect()->route('company.index'); //or even abort(404);
    }

    return $next($request); 
}