web-dev-qa-db-ja.com

Laravel 5.4の `setup / *`を除くすべてのルートにミドルウェアを適用します

Laravelアプリケーションでミドルウェアを試しています。現在、認証済みユーザーのすべてのルートで実行するように設定していますが、setupで始まるすべての要求を無視しますURI。

CheckOnboardingミドルウェアメソッドは次のようになります。

_public function handle($request, Closure $next)
{
    /** 
    * Check to see if the user has completed the onboarding, if not redirect.
    * Also checks that the requested URI isn't the setup route to ensure there isn't a redirect loop.
    */
    if ($request->user()->onboarding_complete == false && $request->path() != 'setup') {
        return redirect('setup');
    } else {
        return $next($request);
    }
}
_

これは私のルートで次のように使用されています:

_Route::group(['middleware' => ['auth','checkOnboarding']], function () {
    Route::get('/home', 'HomeController@index');
    Route::get('/account', 'AccountController@index');

    Route::group(['prefix' => 'setup'], function () {
        Route::get('/', 'OnboardingController@index')->name('setup');
        Route::post('/settings', 'SettingsController@store');
    }); 
});
_

ここで、_/home_または_/account_にアクセスすると、期待どおりに_/setup_にリダイレクトされます。これにより、元々リダイレクトループエラーが発生したため、& $request->path() != 'setup'がミドルウェアに存在するのはなぜですか。

これは本当に不格好な方法だと思いますが、私が作成した_setup/settings_ルートのように、setupの後には明らかに何も一致しません。

このミドルウェアをユーザーのすべてのルートで実行し、このチェックを免除する必要がある特定のルートを設定するより良い方法はありますか?

10
Andy Holmes

あなたがやっていることには何の問題もありませんが、代わりにルートグループを分割することをお勧めします:

Route::group(['middleware' => ['auth', 'checkOnboarding']], function () {
    Route::get('/home', 'HomeController@index');
    Route::get('/account', 'AccountController@index');
});

Route::group(['prefix' => 'setup', 'middleware' => 'auth'], function () {
    Route::get('/', 'OnboardingController@index')->name('setup');
    Route::post('/settings', 'SettingsController@store');
});

または、authの親グループを用意します。

Route::group(['middleware' => 'auth'], function () {

    Route::group(['middleware' => 'checkOnboarding'], function () {
        Route::get('/home', 'HomeController@index');
        Route::get('/account', 'AccountController@index');
    });

    Route::group(['prefix' => 'setup'], function () {
        Route::get('/', 'OnboardingController@index')->name('setup');
        Route::post('/settings', 'SettingsController@store');
    });
});

これは、ミドルウェアの余分な条件を削除できることも意味します。

/**
 * Check to see if the user has completed the onboarding, if not redirect.
 * Also checks that the requested URI isn't the setup route to ensure there isn't a redirect loop.
 */
return $request->user()->onboarding_complete ? $next($request) : redirect('setup');

お役に立てれば!

15
Rwd

このためにControllerクラスを使用すると、かなり素晴らしい結果が得られます。

HTTP/Controllers/Controller.php内に__construct関数を作成すると、すべてのコントローラーアクションで実行するミドルウェアを宣言でき、必要に応じて例外を宣言することもできます。

class Controller extends BaseController
{
  use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
  public function __construct(){
    $this->middleware('auth',['except' => ['login','setup','setupSomethingElse']]);
  }
}

標準のインデックス、ストア、更新、破棄関数を例外に含めないように注意してください。そうしないと、潜在的なセキュリティ問題が発生します。

11
bstory

ミドルウェアを実行したくないルートは、関数の外に置くだけです。

//here register routes on which you dont want the middleware: checkOnboarding
Route::group(['middleware' => ['auth','checkOnboarding']], function () {
     //routes on which you want the middleware
});
2
Learner