One to one relationship in laravel

In database design, relationships are important to perform normalization. With a relationship, we can easily store, retrieve, and validate data. In the Laravel framework, Eloquent provides an easy way to work with database relationships.

In this example, we create two different tables and define the relationship between them. A one-to-one relationship is a very simple and basic relationship compared to others.

To define one to one relationship you just need to make sure that one of the tables has a key that references another table’s ID.

Here, We will create an Employee and Address table. Both tables will be connected using one to one relationship. We will create model migration and relations for those tables.

Create a new Laravel Application

Let’s start with creating a fresh Laravel application for this example. If you already have an existing application then you can skip this step. As you know you can create a new Laravel application with composer using one of the below commands. So open your terminal and enter the below command:

laravel new NAME
//Or
composer create-project --prefer-dist laravel/laravel NAME

Database Configuration

Before starting let’s configure our database. Open the .env file from a root directory and update the below value as per your configuration:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=**********
DB_USERNAME=**********
DB_PASSWORD=**********

Creating Models and Migrations

Here, we have to create two models for this example one is an Employee and the second is an Address. Let’s create them one by one using the terminal:

php artisan make:model Employee -m

It will create an Employee model and migration in our application. Here, the -m flag is responsible for creating a migration file for that model.

Let’s define the database schema for the employee table. Open the employee migration file and modify it as below:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateEmployeesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('employees', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('designation');
            $table->date('dob');
            $table->unsignedBigInteger('number');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('employees');
    }
}

Here, we simply defined name, designation, date of birth, and number fields to store information.

Let’s create a model and migration file for the address table. Same as Employee open terminal and enter below command:

php artisan make:model Address -m

It will create models and migrations for the addresses table. Let’s modify the addresses table and add address field and foreign key for the employees table. Open the address migration file and modify it as below:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateAddressesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('addresses', function (Blueprint $table) {
            $table->id();
            $table->foreignId('employee_id')->constrained();
            $table->text('address');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('addresses');
    }
}

Here we just added two columns. The first one is the Foreign key for the employee table and the second column will be used to store addresses in text data.

Migrate Database

Now, let’s migrate employees and addresses to our database. Open the terminal and enter the below command to migrate:

php artisan migrate

It will create an employees and addresses table in your database.

Defining One to One Relationship In Laravel

Let’s modify the model and define one to one relation between the Employee and Address model. To define a relationship in the employee model, we will create a new method address() in the Employee model. Open app/Models/Employee.php and update as below:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Employee extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'designation',
        'dob',
        'number',
    ];

    public function address(){
        return $this->hasOne(Address::class);
    }
}

In the address method, we used hasOne() and passed the relation model class to it. Next, Eloquent automatically converts queries to fetch data based on relation instances.

Now, we can store and retrieve address information from the employee model but sometimes we require to get Inverse data. So let’s define the Inverse relation between both tables. Open app/Models/Address.php and update as below:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Address extends Model
{
    use HasFactory;

    protected $fillable = [
        'employee_id',
        'address',
    ];

    public function employee(){
        return $this->belongsTo(Employee::class);
    }
}

Same as Employee we have defined the employee method in the address model to get employee information based on one to one relationship with the address table. We have used the belongsTo() method to define an inverse relationship.

Store Data in One-to-One Relationship

To test a relationship, let’s store and retrieve data from both tables. For testing, we have created a controller called HomeController. You can create a new controller or use any existing controller.

There are multiple ways to store data in models. We will discuss freeways in below code snippet.

<?php

namespace App\Http\Controllers;

use App\Models\Address;
use App\Models\Employee;
use Carbon\Carbon;
use Illuminate\Http\Request;

class HomeController extends Controller
{
    public function store(){
        //Using Save method
        $employee = new Employee();
        $employee->name = "Alex";
        $employee->designation = "Manager";
        $employee->dob = Carbon::now()->subYear(rand(18,50));
        $employee->number = 1234567890;
        $employee->save();

        $address = new Address(['address' => 'Test Address']);
        $employee->address()->save($address);

        //Using create method
        $employee = Employee::create([
            'name'=>'Alex',
            'designation'=>'Manager',
            'dob' => Carbon::now()->subYear(rand(18,50)),
            'number'=>1234567890,
        ]);

        $employee->address()->create([
            'address' => 'Test Address',
        ]);
    }
}

Here, we have used save and create a method to store data in both models. For both methods, first of all, we will create an employee model and then create and attach addresses to employees using one to one relationships.

Retrieve Data into One to One Relationship

In below code snippet below, we will see how to retrieve data from both models using the Eloquent relationship. You can use the below code in any PHP class.

$employeeAddress = Employee::find(1)->address;

dd($employeeAddress->toArray());

It will display following output :

array:5 [
    "id" => 1
    "employee_id" => 1
    "address" => "Test"
    "created_at" => "2021-05-30T09:46:24.000000Z"
    "updated_at" => "2021-05-30T09:46:24.000000Z"
]

Here, we find addresses based on employees. Let’s find an employee from the address using an inverse one-to-one relationship.

$employee = Address::find(1)->employee;

dd($employee->toArray());

It will display the following output :

array:7 [
    "id" => 1
    "name" => "test"
    "designation" => "User"
    "dob" => "2022-05-05"
    "number" => 9879879879
    "created_at" => "2021-05-30T09:45:40.000000Z"
    "updated_at" => "2021-05-30T09:45:40.000000Z"
]

You can use that relation instance to eager loading too. Please consider the below example to load data from both models using relation.

$employee = Employee::with(['address'])->find(1);
//Inverse
$address = Address::with(['employee'])->find(1);

It will automatically load both model’s data into a single collection object and you can use it as per your requirement.

Conclusion

Here, We have just created two model employees and addressed them with one-to-one eloquent relationships. We have also performed examples to store and retrieve data with relations in Laravel.