this tutorial was made with laravel 9
There are 3 types of relationships:
- One to One
- One to Many
- Many to Many
In this tutorial I will try to explain the One relation as best as possible
To One since during its realization I encountered different techniques (not always correct).
So we will create the migration, the model, the controller, seeder & factory and finally the test!
Let's begin
One To One
- Create a migration:
php artisan make:migration create_users_table
Schema::create('users', function (Blueprint $table) {
$table->uuid("id")->primary();
$table->string("name", 128);
$table->string("surname", 128);
$table->string("email")->unique();
$table->string("photo")->nullable();
$table->integer("level")->nullable();
$table->string("password");
$table->timestamps();
});
Schema::create('roles', function (Blueprint $table) {
$table->uuid("id")->primary();
$table->string("role")->unique();
$table->uuid('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
//DOWN METHOD
public function down() n{
Schema::drop('roles');
Schema::drop('users');
}
⚠️ It is important to put the deletion of the tables in the correct order, if in this example I had deleted the users table first I would have created an error as the roles table has the foreign key linked to the user.
- Create Model:
php artisan make:model UserModel
Models/User.php
// =====================================
// RELATIONSHIP
// =====================================
public function role()
{
return $this->hasOne(Role::class);
}
and now Model/Role.php
// =====================================
// RELATIONSHIP
// =====================================
public function user()
{
return $this->belongsTo(User::class);
}
And now we can create the updateRole method since it's the only one that cares about the relationship.
Methods like create, show, update and delete can normally be created outside the relationship.
Controller/UserController.php
php artisan make:controller UserController
use App\Models\User;
use App\Models\Role;
public function updateRole(Request $request, $uuid) {
$user = User::find($uuid);
$role = Role::where('user_id', $uuid)->firstOrFail();
$validatedRoleUpdate = $request->validate([
'role' => 'in:admin,user,student,educator',
]);
$role->role = $validatedRoleUpdate['role'];
$user->role()->save($role);
return response()->json([
'status' => true,
'message' => 'User Role Update Successfully',
], 200);
}
Well, now we do Seeder and Factory:
php artisan make:factory UserFactory
factories/UserFactory.php
public function definition(){
return [
'name' => fake()->name(),
'surname' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
];
}
factories/RoleFactory.php
public function definition() {
return [
'role' => 'user',
];
}
seeders/UserSeeder.php
php artisan make:seeder UserSeeder
$user = User::factory()
->has(Role::factory())
->create();
Last step let's test the updateRole method
php artisan make:test UserTest --unit
/*
Command for run a specific test
./vendor/bin/phpunit --filter testUpdateRole tests/Unit/UserControllerTest.php
*/
public function testUpdateRole() {
$id = User::all()->first()['id'];
$response = $this->put("/api/users/{$id}/role", ['role' => 'student']);
$response->assertStatus(200)->assertJson([
'message' => 'User Role Update Successfully',
]);
}
Well in our database we will now have a connected role created for each user and vice versa, each role has its own connected user.
For this personal project it had to be done this way, but it could just as well have added the 'role_id' field in the user table.
In the next articles I will explain how relationships between tables can get complicated!
Top comments (0)