Laravel 8 Multiple Routes With The Same Url

3.9k views Asked by At

Good Day

I'm new to Laravel, and I want to create a website that has multiple users (Student, Supervisor, HOD). I want to know if there is a way to have all the users have the same URLs. Below is the approach I used to try to achieve this:

web.php

// Routes For Students
Route::group(['middleware' => ['auth', 'role:student']], function() {
    Route::get('/home', 'App\Http\Controllers\StudentController@index')->name('student');
    Route::get('/proposal', 'App\Http\Controllers\StudentController@proposal')->name('proposal');
    Route::get('/thesis', 'App\Http\Controllers\StudentController@thesis')->name('thesis');
});

// Routes For Supervisors
Route::group(['middleware' => ['auth', 'role:supervisor']], function() {
    Route::get('/home', 'App\Http\Controllers\supervisorController@index')->name('supervisor');
    Route::get('/proposal', 'App\Http\Controllers\supervisorController@proposal')->name('proposal');
    Route::get('/thesis', 'App\Http\Controllers\supervisorController@thesis')->name('thesis');
});

// Routes For HOD's
Route::group(['middleware' => ['auth', 'role:hod']], function() {
    Route::get('/home', 'App\Http\Controllers\hodController@index')->name('hod');
    Route::get('/proposal', 'App\Http\Controllers\hodController@proposal')->name('proposal');
    Route::get('/thesis', 'App\Http\Controllers\hodController@thesis')->name('thesis');
});

However I noticed that you cannot have routes with the same URL, but I want all types of users to have the same URL for their respective home, proposal & thesis pages. Is this possible?

Please let me know if you require more code or a better explanation.

3

There are 3 answers

3
IGP On BEST ANSWER

I'd advise just adding a prefix to all those routes. That way you don't get any duplicate uris.


If you really don't want to do that, I've got another possibility, but you won't be able to keep the route names.

Basically, use an invokable controller to reroute to the correct controller/action.

php artisan make:controller -i
Route::group(['middleware' => ['auth']], function () {
    Route::get('/home', 'App\Http\Controllers\MyInvokableController')->name('home');
    Route::get('/proposal', 'App\Http\Controllers\MyInvokableController')->name('proposal');
    Route::get('/thesis', 'App\Http\Controllers\MyInvokableController')->name('thesis');
});
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class MyInvokableController extends Controller
{
    private $lookupArray = [
        'home'     => 'index',
        'proposal' => 'proposal',
        'thesis'   => 'thesis',
    ];

    public function __invoke(Request $request)
    {
        $role = ;// get your user's role
        $urlSegment = $request->segment(count($request->segments()) - 1); // 'home', 'proposal' or 'thesis'

        if ($role === 'student') {
            return app(StudentController::class)->{$this->lookupArray[$urlSegment]}($request);
        } elseif ($role === 'supervisor') {
            return app(supervisorController::class)->{$this->lookupArray[$urlSegment]}($request);
        } elseif ($role === 'hod') {
            return app(hodController::class)->{$this->lookupArray[$urlSegment]}($request);
        } else {
            throw new \Exception("Unexpected role $role.");
        }
    }
}
3
Professor On

If you need to keep the same routes, you can either follow @IGP answer or just check the user role on the blade itself.

// welcome.blade.php
@role('student')
    <h1>Student welcome page</h1>
@endrole

@role('supervisor')
    <h1>Supervisor welcome page</h1>
@endrole

@role('hod')
    <h1>Hod welcome page</h1>
@endrole
1
amrezzd On

I think you better to handle the logic on your controller rather than role middleware. Could be there any Supervisor having Student "role"? No. That's because Supervisor is not a role here, it's the user type. So here you want the same URL, this is what I prefer:

Route::group(['middleware' => ['auth']], function() {
    Route::get('/home', 'App\Http\Controllers\Controller@index')->name('home');
    Route::get('/proposal', 'App\Http\Controllers\Controller@proposal')->name('proposal');
    Route::get('/thesis', 'App\Http\Controllers\Controller@thesis')->name('thesis');
});

Handle the user type behind the scene.

public function index(Request $request) 
{
    // handle the request, determine the user type, populate the proper view, etc.
}

Now about the role,

Middleware can also receive additional parameters. For example, if your application needs to verify that the authenticated user has a given "role" before performing a given action. Laravel 8 Documentation - Middleware

To give an example, you can have say "presenter" role on your application which has a unique URLs and Students and Supervisors are allowed to access them.

Just using Middlewares doesn't mean it would be an efficient solution. As documentation says:

Middleware provide a convenient mechanism for inspecting and filtering HTTP requests entering your application. Laravel Documentation