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 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 below command:

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

Database Configuration

Before starting let's configure our database. Open .env file from root directory and update 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 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, -m flag is responsible for creating a migration file for that model.

Let's define the database schema for employee table. Open 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 addresses table. Let's modify addresses table and add address field and foreign key for employees table. Open 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 Foreign key for employee table and second column will be used to store addresses in text data.

Migrate Database

Now, let's migrate employees and addresses to our database. Open terminal and enter 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 model and define one to one relation between Employee and Address model. To define a relationship in employee model, we will create a new method address() in 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 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 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 employee method in address model to get employee information based on one to one relationship with address table. We have used belongsTo() method to define an inverse relationship.

Testing

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.

Store Data in One-to-One Relationship

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 employee model and then create and attach addresses to employee using one to one relationship.

Retrieve Data into One to One Relationship

In below code snippet, we will see how to retrieve data from both models using the Eloquent relationship. You can use 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 employee. Let's find employee from address using an inverse one-to-one relationship.

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

dd($employee->toArray());

It will display 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 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 models data into a single collection object and you can use it as per your requirement.

Conclusion

Here, We have just created two models employee and address with one-to-one eloquent relationship. We have also performed examples to store and retrieve data with relations in Laravel.