Let's say I have the following routes file:
Route::group(['middleware' => 'foo.only'], function () {
Route::get('/', 'FooController#index');
Route::get('/about', 'FooController#about');
});
Route::get('/', 'BarController#index');
Route::get('/about', 'BarController#about');
In my FooOnlyMiddleware handler I have something like:
public function handle($request, $next)
{
if ($foo == true) {
return $next($request);
}
else {
// skip the entire route group and move onto the next route
}
}
How do I do this so that if $foo = false it will skip the entire route group and move onto the bar routes?
This won't work, as both of your foo and bar routes are the same:
Route::get('/', 'FooController#index');
Route::get('/', 'BarController#index');
The bar route will never be reached.
Here is one way to accomplish the conditional routes you want:
Your routes:
Route::group(['middleware' => 'foo.only'], function () {
Route::get('/', 'FooController#index');
Route::get('/about', 'FooController#about');
});
Route::get('bar/', 'BarController#index');
Route::get('bar/about', 'BarController#about');
FooOnlyMiddleware:
public function handle($request, $next)
{
if ($foo == true) {
return $next($request);
}
else {
return redirect('/bar/'.$request->route()->uri());
}
}
Of course, this would be valid if every route using the FooOnlyMiddleware, has an equivalent bar route. Otherwise, just redirect to any route you want.
Related
Hello i tried to use middleware like the code below to validate OR operator
Route::get('/page', [Controller::class, 'index'])->middleware(['mid1','mid2']);
in this example it uses the AND operator not OR I used also groups like this
Route::group(['middleware' => 'mid1'], function () {
Route::get('/page', [Controller::class, 'index']);
});
Route::group(['middleware' => 'mid2'], function () {
Route::get('/page', [Controller::class, 'index']);
});
but using groups with same route the second route in the group is the only one readable.
Any help please
There's nothing builtin in laravel to do such a thing.
You can create another middle-ware to contain both conditions you need to apply.
In you middleware:
public function handle($request, Closure $next) {
if (condition1 || condition2) {
return $request($next);
}
abort('statusCode');
}
I agree with #Faesal. It would be best to combine two middleware logic into one middleware.
public function handle($request, Closure $next) {
if (your condition) {
//logic inside mid1 handler
}else{
//logic inside mid2 handler
}
}
Although it is not recommended but you can put your conditions in route file.
if(your conditions){
Route::group(['middleware' => 'mid1'], function () {
Route::get('/page', [Controller::class, 'index']);
});
}else{
Route::group(['middleware' => 'mid2'], function () {
Route::get('/page', [Controller::class, 'index']);
});
}
How does it(route:caching) work under hood and will it breake logic if I cached my routes.
I have a webhook which send me data to one single route. The data are difference only by objects fields. Will it correct to split it to different routes or I am need to make index method which will be redirect my logic by methods
Route::group(['namespace' => 'Webhook'], function () {
if (Request::has('message')) {
Route::post('/', 'WebhookController#message');
}
if (Request::has('callback_query')) {
Route::post('/', 'WebhookController#callback');
}
});
You can shorten the routes code to this:
Route::group(['namespace' => 'Webhook'], function () {
Route::post('/', 'WebhookController#handle');
});
And do the "heavy work" in the controller:
class WebhookController extends Controller
{
public function handle(Request $request)
{
if ($request->has('message')) {
return $this->message();
}
if ($request->has('callback_query')) {
return $this->callback();
}
}
public function message();
public function callback();
}
This is equivalent to:
Route::group(['namespace' => 'Webhook'], function () {
Route::post('/', function(Request $request) {
if ($request->has('message')) {
return (new WebhookController)->message();
}
if ($request->has('callback_query')) {
return (new WebhookController)->callback();
}
});
});
You can use middleware for such kind of logics.
Laravel Middleware
I have a route with an optional parameter in web.php:
my web.php: (the route that has the problem is marked with a comment)
Route::middleware(['auth', 'dashboard'])->group(function () {
Route::get('/', 'DashboardController#home')->name('root');
Route::prefix('/drivers')->group(function () {
Route::view('/', 'dashboard.driver.main');
Route::post('/', 'UserController#addDriver');
Route::get('/{id}', function ($id) {
if (Auth::user()->can('view_user')) {
$user = User::find($id);
return view('dashboard.user.view', ['user' => $user]);
}
return view('pages.403');
});
//----------------------------------------
// My route with the problem
// ---------------------------------------
Route::get('/driver-dropdown/{q?}', function ($q=null){
return $q;
})->name('driver.dropdown');
});
});
and it is my dashboard middleware:
public function handle($request, Closure $next)
{
if(!in_array(\Auth::user()->getOriginal('role'), ['superadmin', 'admin', 'supporter']) )
{
return abort(403);
}
return $next($request);
}
When I enter the host-name/drivers/driver-dropdown/jo URL, I get jo
BUT When I enter the host-name/drivers/driver-dropdown/ URL, I will be redirected to the host-name/ that means root route!
Edit: updated web.php
You should reorder your routes like this:
Route::get('/driver-dropdown/{q?}', function ($q=null){
return $q;
})->name('driver.dropdown');
Route::get('/{id}', function ($id) {
if (Auth::user()->can('view_user')) {
$user = User::find($id);
return view('dashboard.user.view', ['user' => $user]);
}
return view('pages.403');
});
Currently, when you go to host-name/drivers/driver-dropdown/, it will match the /{id} route.
If I’m correct the URL’s in your routes which are grouped shouldn’t start with a /, except for the main route of course. I’ve had this issue too.
Should be like this:
Route::middleware(['auth', 'dashboard'])->group(function () {
Route::get('/', 'DashboardController#home')->name('root');
Route::prefix('drivers')->group(function () {
Route::get('driver-dropdown/{q?}', function ($q=null){
return $q;
})->name('driver.dropdown');
});
});
so im trying to put my localization as prefix on my website domain so i made a middleware the puts the localization lang on the url ever time you try to open a page heres my middleware
public function handle($request, Closure $next)
{
if ($request->method() === 'GET') {
$segment = $request->segment(1);
if (!in_array($segment, config('app.locales'))) {
$segments = $request->segments();
$fallback = session('locale') ?: config('app.fallback_locale');
$segments = array_prepend($segments, $fallback);
return redirect()->to(implode('/', $segments));
}
session(['locale' => $segment]);
app()->setLocale($segment);
}
return $next($request);
}
and i added the middleware to the routemiddleware
protected $routeMiddleware = [
'Locate' => \App\Http\Middleware\Locale::class,
];
and i did put a prefix and middleware to all my routes like this
Route::prefix('{lang?}')->middleware('Locate')->group(function() {
Route::get('logout', '\App\Http\Controllers\Auth\LoginController#logout')->name('logout');
Route::get('/home', 'HomeController#index')->name('home');
Route::get('/admin/login', function () {
return view('admin.auth.login');
})->name('AdminLogin');
Route::get('/contact-us', 'ContactUsController#Contactus')->name('ContactUs');
Route::post('/contact-us', 'ContactUsController#PostContactus')->name('PostContactUs');
Route::prefix('auth')->group(function () {
Route::get('/login', function () {
return view('auth.login');
})->name('Login');
Route::post('/login', 'Auth\LoginController#Login')->name('userslogin');
});
Route::prefix('search')->group(function () {
Route::get('/categories', 'search\SearchController#Categories')->name('Categories');
Route::get('/filter/{categoryseo}', 'search\SearchController#filter')->name('InstructorsSearch');
//sending categoryseo to the filter page so i can put it in hidden input in the filter page and use it to get the list
Route::get('/list', 'search\SearchController#InstructorList')->name('InstructorsSearchList');
Route::get('/profile/{userid?}', 'search\SearchController#instructorprofile')->name('InstructorProfile');
});
});
for some reason pages like /home gets the to the middleware and change as i wanted like this /en/home , as for other like search/categories it wont even notice my middleware but i tried to remove the prefix of the localization and just put my middleware it worked and it notice my middleware. using laravel 5.5
I would like show other main page after login to the user.
Route::get('/', 'PagesController#getIndex');
Route::group(['middleware' => 'auth'], function () {
Route::get('/', 'BlogController#getUserBlog');
});
When user is log in I would like to show BlogController#getUserBlog it's working but, when user is not authenticated laravel shows /login page not PagesController#getIndex. How to correct this for:
Auth user: BlogController#getUserBlog
Guest: PagesController#getIndex
Make changes in this Middleware RedirectIfAuthenticated
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
//Logged In
return redirect()->route('getUserBlog');
}
// Not Logged In
return redirect()->route('getIndex');
}
and make the necessary change in your routes file
Route::get('/', 'PagesController#getIndex')->name('getIndex');
Route::get('/', 'BlogController#getUserBlog')->name('getUserBlog');
Or you can do it without middleware :
Route::group(['prefix' => '/'], function()
{
if ( Auth::check() )
{
Route::get('/', 'BlogController#getUserBlog');
} else{
Route::get('/', 'PagesController#getIndex');
}
});