I’m experimenting with Middleware in my Laravel application. I currently have it set up to run on every route for an authenticated user, however, I want it to ignore any requests that begin with the setup
URI.
Here is what my CheckOnboarding
middleware method looks like:
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); } }
This is being used in my routes like this:
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'); }); });
Now, if I go to /home
or /account
I get redirected to /setup
as you would expect. This originally caused a redirect loop error hence why & $request->path() != 'setup'
is in the Middleware.
I feel like this is a really clunky way of doing it, and obviously doesn’t match anything after setup
like the setup/settings
route I have created.
Is there a better way to have this Middleware run on all routes for a user, but also set certain routes that should be exempt from this check?
Advertisement
Answer
There’s nothing wrong with what you’re doing, however, I would suggest splitting your route groups up instead i.e.:
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'); });
Alternatively, have a parent group for your 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'); }); });
This will also mean you can remove the extra condition in your middleware:
/** * 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');
Hope this helps!