Laravel one to one eloquent relationship tutorial with example

#Introduction

In this tutorial, we will learn one to one relationship with example.

Let's assume we have two table user and passport. So a user can have one passport number and passport number has one user.

For this tutorial, I'll use already created Laravel project. If you have not set up you can follow below link to install fresh Laravel installation.

Install Fresh Laravel Project

Step 1. Create migration

For this tutorial, we will need two table to setup the one to one relationship.

  1. User
  2. Passport

By default Laravel ships migration for user table under database/migrations and model file under app directory. I will use the default migration file for this tutorial.

Now let's create a migration and model for passport table.

php artisan make:migration create_passports_table

Now create a model for passport table.

php artisan make:model Passport

Note: You can also run php artisan make:model Passport -m to create migration and model together.

Now edit the passport migration file and add the following schema

#database/migrations/2019_09_17_174021_create_passport_table.php

public function up()
{
    Schema::create('passport', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->integer('user_id');
        $table->string('passport_number')->unique();
        $table->timestamps();
    });
}

and run the following command to create the table.

php artisan migrate
 

Step 2. Insert dummy data using Laravel factories

For this topic, we will use dummy data to test the one to one relationship. So, Let's quickly create a passport factory and seeder class with the following command.

php artisan make:factory PassportFactory
php artisan make:seeder PassportSeeder

The above command will create a factory and a seeder class under the database/factory and database/seeders directory. Now edit the passport factory class and add the following class

#database/factories/PassportFactory.php

use App\Passport;
use Faker\Generator as Faker;

$factory->define(Passport::class, function (Faker $faker) {
    return [
        'user_id' => rand(1, 20),
        'passport_number' => $faker->unique()->randomNumber($nbDigits = 9)
    ];
});

Next, edit the Passport seeder class and add the following code.

#database/seeds/PassportSeeder.php

public function run()
{
    factory('App\Passport', 20)->create();
}

The above code will create 20 unique passports number. 

Next same thing for user table. Run the below command to create user factory and seeder class

php artisan make:factory UserFactory
php artisan make:seeder UserSeeder

#database/factories/UserFactory.php

$factory->define(User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
        'remember_token' => Str::random(10),
    ];
});

Don't forget to import user model class. Now add the following code to UserSeeder class

#database/seeds/UserSeeder.php

public function run()
{
    factory('App\User', 20)->create();
}

Once you are done with adding the above code. Now add the following code to the DatabaseSeeder class

#database/seeds/DatabaseSeeder.php 

public function run()
{
    $this->call(UserSeeder::class);
    $this->call(PassportSeeder::class);
}

Now run the below code to seed the database

php artisan db:seed

Step 3. Setting one to one relationship

Go to user model and add the following code

public function passport()
{
    return $this->hasOne('App\Passport');
}

Now to access the user's passport number. Go to your controller and add the following code in your function. Eg: my controller is HomeController and the function name is index. import the user model and add the following code in your function.

$user = User::find(1);
dd($user->passport);

User::find(1) will get all the user details associated with id 1. If you call the passport function it will display all the passport details associated with user id 1.

If you dump the eloquent query then you will get the following SQL query.

[
	{
		query: "select * from `users` where `users`.`id` = ? limit 1",
		bindings: [
			1
		],
		time: 2.51
	},
	{
		query: "select * from `passports` where `passports`.`user_id` = ? and `passports`.`user_id` is not null limit 1",
		bindings: [
			1
		],
		time: 0.42
	}
]

Step 4. Setting an inverse relationship

Go to passport model and add the below code to set the inverse relationship

public function user()
{
	return $this->belongsTo('App\User');
}

To access the user detail by passport number Go to your controller and add the below code.

$passport = App\Passport::find(1);
dd($passport->user);

The above query will fetch all the user detail associated with passport id 1.

If you dump the above eloquent query you will get the below SQL query.

[
	{
		query: "select * from `passports` where `passports`.`id` = ? limit 1",
		bindings: [
			1
		],
		time: 1.73
	},
	{
		query: "select * from `users` where `users`.`id` = ? limit 1",
		bindings: [
			18
		],
		time: 0.94
	}
]

Tip #1: To get passport details with the user in the same collection. You can use the laravel with() function. for example

$passport = App\User::findOrFail(1)->with('passport')->first();
return $passport;

Tip #2: To dump the eloquent query you can use below code

\DB::enableQueryLog();
// your eloquent query
return \DB::getQueryLog();

Thank you for reading!