Back to Course |
[Mini-Course] Laravel 11: Breeze with User Role Areas

Role Model/Migrations, Seeder and Teacher Registration

Finally, let's move to the second role: teachers. Let's also enable registration for them. We will have a radio input on the register page to select a role.


Roles: Model and Migrations

First, we must take care of the backend. Let's introduce a role. We will have a Role Model and add a role relationship to the User Model. So, first, the Model with Migrations.

php artisan make:model Role -m
php artisan make:migration "add role id to users table"

app/Models/Role.php:

class Role extends Model
{
protected $fillable = [
'name',
];
}

database/migrations/xxx_create_roles_table.php:

Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});

database/migrations/xxx_add_role_id_to_users_table.php:

Schema::table('users', function (Blueprint $table) {
$table->foreignId('role_id')->constrained();
});

app/Models/User.php:

class User extends Authenticatable
{
use HasFactory, Notifiable;
 
protected $fillable = [
'name',
'email',
'password',
'role_id',
];
 
// ...
}

Now, let's seed student and teacher roles.

database/seeders/DatabaseSeeder.php:

use App\Models\Role;
 
class DatabaseSeeder extends Seeder
{
public function run(): void
{
Role::create(['name' => 'student']);
Role::create(['name' => 'teacher']);
}
}

Refresh the migrations with the seed.

php artisan migrate:fresh --seed

Registration Page: Choose Role

Next, let's add a radio input to select a role.

resources/views/auth/register.blade.php:

<x-guest-layout>
<form method="POST" action="{{ route('register') }}">
// ...
 
<!-- Role -->
<div class="mt-4">
<x-input-label for="role_id" :value="__('Register as:')" />
 
<label>
<input type="radio" name="role_id" value="1" checked /> Student
</label>
<label class="ml-2">
<input type="radio" name="role_id" value="2" /> Teacher
</label>
 
<x-input-error :messages="$errors->get('role_id')" class="mt-2" />
</div>
 
<div class="flex items-center justify-end mt-4">
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('login') }}">
{{ __('Already registered?') }}
</a>
 
<x-primary-button class="ms-4">
{{ __('Register') }}
</x-primary-button>
</div>
</form>
</x-guest-layout>


Register Submit: Save Role

Finally, we must save the role to the database.

app/Http/Controllers/Auth/RegisteredUserController.php:

class RegisteredUserController extends Controller
{
// ...
 
public function store(Request $request): RedirectResponse
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
'role_id' => ['required', 'in:1,2'],
]);
 
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
'role_id' => $request->role_id,
]);
 
event(new Registered($user));
 
Auth::login($user);
 
return redirect(route('student.timetable', absolute: false));
}
}

Notice: for the validation, we use the in validation rule instead of exists because we can only register with these two roles. We want users to refrain from registering with an admin role.

After registering with the teacher role in the database, we see that the correct role is set.


But now the teacher is still landing in the Student area? In the next lesson, we will start separating student and teacher areas.