Apply Middleware to all routes except `setup/*` in Laravel 5.4
Since Laravel 7.7 you can use excluded_middleware
like this:
Route::group(['middleware' => ['auth','checkOnboarding']], function () {
Route::get('/home', 'HomeController@index');
Route::get('/account', 'AccountController@index');
Route::group([
'prefix' => 'setup',
'excluded_middleware' => ['checkOnboarding'],
], function () {
Route::get('/', 'OnboardingController@index')->name('setup');
Route::post('/settings', 'SettingsController@store');
});
});
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!
There are 2 ways to go over this problem
- Try screening your routes in routes file
web.php or api.php
- skip routes in
middleware
In case of global middleware (middleware that you want to run before all routes), you should go with skipping routes in middleware.
For example:
//add an array of routes to skip santize check
protected $openRoutes = [
'setup/*',
];
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if(!in_array($request->path(), $this->openRoutes)){
//middleware code or call of function
}
return $next($request);
}
For other middleware, you can easily skip in routes file and group routes based on your middleware.
For example:
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');
});
You can utilize the Controller class for this with pretty spectacular results.
If you create a __construct function inside of HTTP/Controllers/Controller.php then you can declare middleware to run on every controller action and even declare exceptions as needed.
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function __construct(){
$this->middleware('auth',['except' => ['login','setup','setupSomethingElse']]);
}
}
Be careful not to put any of the standard index, store, update, destroy functions in the exception or you'll open up potential security issues.