0

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.

EricSchaefer
  • 25,272
  • 21
  • 67
  • 103
Helder Doggo
  • 13
  • 1
  • 5

3 Answers3

1

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.");
        }
    }
}
IGP
  • 14,160
  • 4
  • 26
  • 43
  • Thanks for the answer. If I had to add a prefix, what would it be in your opinion? Perhaps the user id? Or some randomly generated number? – Helder Doggo May 16 '21 at 01:30
  • Nothing so complicated. Just `prefix('student')` for student routes, `prefix('supervisor')` for supervisor routes and `prefix('hod')` for hod routes. That way you can have the urls `/student/home`, `/supervisor/home` and `/hod/home`. I'm talking about Route prefixes you'd add in your grouping. `Route::prefix('hod')->name('hod.')->group(['middleware' => ['auth']], function () {` – IGP May 16 '21 at 04:57
  • Ah, ok. First time posting a question, glad I could get such good help. Thanks. – Helder Doggo May 16 '21 at 14:50
0

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
Professor
  • 858
  • 1
  • 9
  • 17
  • Thanks for the answer. This was what I was thinking, however I was wondering about how efficient that would be if each user type has alot going on in their respective pages. Any thoughts on that? – Helder Doggo May 16 '21 at 01:00
  • Well, since the code inside the @role snippets won't be executed if the user is not assigned that role, you may simply move those contents into separate blades (just for clarity) and add a `@include('-welcome-page')` to load the content of each role. I don't think there will be any performance issue, just a lot of code together if it doesn't get split correctly. – Professor May 16 '21 at 01:20
  • Ok, if there won't be any performance issues then this is definitely the way to go. Thanks. – Helder Doggo May 16 '21 at 01:32
0

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

amrezzd
  • 1,787
  • 15
  • 38