Laravel One to One Relationship: A Beginner’s Guide
Last Updated on June 8, 2024
One-to-one relationships occur when one Entity in the database has an association with another record from another Entity. For example, in a company, each Staff member can have one staff ID code, and each ID Code belongs to one staff member.
This showcases a one-to-one entity relationship where each staff has one code they use to access the Company’s premises.
In this article, I am going to show you how to implement a One-to-one Relationship in Laravel
How do you implement a one-to-one relationship in Laravel?
To implement one to one relationship, we will need to follow these steps
1. Create a Laravel Project
The first step is to create a Laravel project if you don’t have one. You can use the Laravel new command if you have Laravel installed globally.
laravel new test
2. Create a Staff Model and Migration
The next step is to create the Staff Model and migration file. We can think of it as the Parent Model because it has to exist for a staff code also to exist.
php artisan make:model Staff -m
This will generate the model and its corresponding migration file. I will update the Model and migration files to resemble the ones below
<?php
namespace App\Models;
use App\Models\StaffCodes;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Staff extends Model
{
use HasFactory;
protected $fillable = ['name','email','phonenumber'];
public function staff_code()
{
return $this->hasOne(StaffCodes::class,'staff_id');
}
}
Staff Model
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('staff', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email');
$table->string('phonenumber');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('staff');
}
};
Staff Migration File
3. Create a Staff Code Model and Migration
The other model to create is the Staff Code Model
php artisan make:model StaffCodes -m
The -m flag creates a migration file together with your Model. Similar to the Staff’s Model, I will update the StaffCode’s model and migration files
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class StaffCodes extends Model
{
use HasFactory;
protected $fillable = ['staff_id','code'];
public function staff()
{
return $this->belongsTo(Staff::class,'staff_id');
}
}
StaffCode’s Model
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('staff_codes', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('staff_id')->index();
$table->integer('code');
$table->timestamps();
$table->foreign('staff_id')->references('id')->on('staff')->cascadeOnDelete();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('staff_codes');
}
};
StaffCodes’s migration file
4. Define the One to One Relationship
Now that our Models are ready, it is now time to update the Migration files and the Model. In this case, we have two Models where one is the Parent Model(Staff Model) and the Child Model(Staff Codes Model). Laravel Eloquent helps us define the one-to-one relationship easily and cleanly.
We can update the Staff Model by adding a hasOne() function. This illustrates to Laravel that it is the Parent Model. We can also update the StaffCodes Model and add the belongsTo() method.
In those methods, we can define the foreign keys as I find it easier and bug-free when I define them.
public function staff()
{
return $this->belongsTo(Staff::class,'staff_id');
}
StaffCodes Model
public function staff_code()
{
return $this->hasOne(StaffCodes::class,'staff_id');
}
Staff Model
Once we have defined the relationship, we can now migrate the database.
php artisan migrate
5. Leveraging the Relationship in our Controller
Now that the relationship is defined and the database has been migrated, we can use Eloquent’s power to interact with our database.
We will first start by adding records to the database. We will create a controller to do so
php artisan make:controller StaffController -r
The -r flag instructs artisan to create a resourceful controller. This basically means that our controller will have all the basic methods such as index store update and destroy that we will use to interact with the database
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class StaffCodeController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
We will first start by handling the store method. This method is responsible for adding records to the database. In our StaffCodes model earlier we had specified that a foreign key for the Staff’s model is required. Therefore, we need a way to include it as part of the inputs we get from a form.
public function store(Request $request)
{
$data = [
'staff_id' => $request->input('staff'), //The foreign key of the staff
'code' => rand(1000, 1000000), //generate random staff code
];
StaffCodes::create($data);
return redirect('staff')->with('success', 'Staff Code Created Successfully');
}
This is will be similar in the update method. We will also need to pass the staff’s foreign key as part of the input
public function update(Request $request, $id)
{
$staff_code = StaffCodes::find($id);
$data = [
'staff_id' => $request->has('staff') ? $request->input('staff') : $staff_code->code, //The foreign key of the staff
'code' => $request->has('code') ? $request->input('code') : rand(1000, 1000000), //generate random staff code
];
$staff_code->update($data);
return redirect('staff')->with('success', 'Staff Code Updated Successfully');
}
In the update method, we are doing some conditional logic by checking if a request parameter such as staff or code has been provided or updated. If so, we change the record; otherwise, we use the record in the database.
With that, our application is almost done.
6. Create/Update Child Records from the Parent Model
We can also manipulate the child records directly from the Parent Model in Laravel. Say you want to onboard a new staff to your company and you need to generate a staff code for them; you can use the relationships functions we created to do so
public function store(Request $request)
{
$staff_data = [
'name' => $request->input('name'), //John
'email' => $request->input('name'), //john@example.com
'phonenumber' => $request->input('phonenumber'), //John's Phone number
];
$staff = Staff::create($staff_data);
$staff->staff_code()->create([
'staff_id'=>$staff->id,
'code' => rand(1000, 1000000)
]);
return redirect('staff')->with('success', 'Staff Details Added Successfully');
}
This makes it easy to update/create these records with little lines of code
7. Retrieve Records
The last step is to retrieve the records. In this part, we want to avoid introducing the N+1 query problem. This means that we don’t want our application to send multiple queries to the database for it to retrieve the records(lazy loading)
An example of an N+1 query is shown below.
$staff_members = Staff::all();
foreach($staff_members as $staff)
{
$staff->staff_code->code;
}
At face level, this looks like a good query but in the background, multiple queries are being made to the database.
To fix this, we can use the with() method provided by Laravel. This will eager load the records and therefore result in fewer queries to the database and, therefore, increase the performance of the application
$staff_members = Staff::with('staff_code')->get();
foreach($staff_members as $staff)
{
$staff->staff_code->code;
}
And that’s it. We have created a One-to-one relationship in Laravel
Conclusion
In this tutorial, you learnt how to implement one-to-one relationships in Laravel. I hope this article was helpful. I also wrote other articles on how to implement many-to-many relationships in Laravel and how to implement one-to-many relationships in Laravel. You can give them a read. If you have any questions, feel free to ask. Thank you for reading.