ホーム > Laravel > How to Implement One-to-One Relationships in Laravel and How to Retrieve and Use Data【hasOne】
Laravel

How to Implement One-to-One Relationships in Laravel and How to Retrieve and Use Data【hasOne】

Thank you for your continued support.
This article contains advertisements that help fund our operations.

This article summarizes how to implement one-to-one relationships in Laravel and how to retrieve and use data.

What is a Relationship?

It refers to data that has a relationship between database tables.

What is a Relationship

In this example, we have two tables, users and user_details, where data is linked based on the user ID.

In other words, if we store user_id in the user_details table, we can establish a relationship.

Laravel makes it easy to implement this with a little coding.

Laravel 11.x Eloquent: Relationships One-to-One / HasOne

Testing Environment

The testing environment is Laravel 11, but it will work on Laravel 8 or later since no changes have been made.

How to Implement One-to-One Relationships

Table Design

Relationship Design

Create the user_details Table

Create Migration File with Command

php artisan make:migration create_user_details_table

Write in the Migration File

database/migrations/2024_10_29_003907_create_user_details_table.php

Schema::create('user_details', function (Blueprint $table) {
    $table->id();
    $table->bigInteger('user_id'); // Important
    $table->string('address');
    $table->timestamps();
});

Run the Migration to Modify the Database

php artisan migrate

Create UserDetail Model with Command

php artisan make:model UserDetail

Write in the User Model

app/Models/User.php

class User extends Authenticatable
{
    // *omitted*
    public function userDetail()
    {
        return $this->hasOne(UserDetail::class);
    }
}

Using hasOne, we can define a one-to-one relationship in the model.

By the way, the UserDetail::class part is based on the app/Models/ directory.

So, if the model class is located at app/Models/User/UserDetail.php, it should be written as User\UserDetail::class.

Write the Relationship in the Controller

use App\Models\User;

~~~~~~~~
    public function index()
    {
        $users = User::with('userDetail')->get();
        // dd($users);
        return view('home',compact('users'));
    }
}

userDetail is the function name written in the model.

with is for Eager loading, which stabilizes the number of data retrievals and helps resolve issues like the N+1 problem, so it's safer to use.

How to Display Relationship Data

In a Blade File

@foreach($users as $user)
  {{ $user->userDetail->address }}
@endforeach

By connecting userDetail->address with the relationship function and the desired column, you can display the data.

Note that $users->userDetail->address cannot be used.

You must specify the relationship for each individual instance.

In React

When displaying in JavaScript, the relationship becomes snake_case instead of camelCase.

{
  users.map(user => <div key={user.id}>{user.user_detail.address}</div>)
}

In Vue

<template>
  <div v-for="user in users">
    {{ user.user_detail.address }}
  </div>
</template>

Relating users Based on user_details

You can obtain related data by reversing the base table in the relationship.

Write in the UserDetail Model

app\Models\UserDetail.php

class UserDetail extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Using belongsTo, you can retrieve related data by reversing the base table as shown above.

Whether to use hasOne or belongsTo is determined at the design stage when defining users.id = user_details.user_id, so you'll learn this through practice over time.

At first, it's okay to get it working, and you don't need to memorize it before moving on.

Since it's a binary choice, you can just try both.

Write in the Controller

    public function index()
    {
        $users = UserDetail::with('user')->get();
        // dd($users);
        return view('home',compact('users'));
    }
}

Advantages of One-to-One Relationships

Generally Redundant

One-to-one relationships are generally redundant.

This is because you can achieve the same functionality by simply adding an address column to the users table.

Therefore, there isn't often a necessity to implement a relationship just for the sake of having one; a solid justification for using a relationship is usually required.

Performance Improvement During Display

Typically, this data is stored in separate tables for specific cases where it is not displayed in the user list but may be used during user information registration.

In pages that handle many records and display lists, it's better to store only the necessary columns in the table rather than filtering columns using select, which can reduce processing load and transfer volume. The more records you have, the more performance differences you will notice.

Since this varies with the amount of data, it may be hard to notice initially, leading many products to address this only after experiencing issues.

Security Measures

This involves managing data that needs to be handled strictly in separate tables.

If data can be seen unintentionally when returned, it poses a problem, so separating tables serves to prevent such accidents.

Ease of Management

It might be easier to manage when tables are separated.

You need to decide whether to manage based on display or input; otherwise, you'll just end up with separate tables without purpose.

Capacity Limitations of Tables (Rare)

This issue arises when you create tables with many free-text input columns.

There are rare cases where a limit on what can be saved in a single table is reached, necessitating the separation of tables.

Is a Foreign Key Necessary?

What is a Foreign Key?

A foreign key defines the relationship between tables and maintains data integrity.

For instance, if parent data is deleted, the related child data is also deleted, maintaining data integrity—this is the role of the foreign key.

The foreign key is not set in Laravel but rather on the database side and is configured during migration.

Foreign Key is Not Mandatory

There are various opinions on this, but I personally believe it's not mandatory.

If you feel it's necessary after consulting the specifications, it’s better to set a foreign key.

In cases where there is no particular reason, it is usually fine not to set one.

While it's possible for bugs or errors to arise from data floating around, whether to handle them with foreign keys or other methods depends on the specific case.

Beginners Can Skip Foreign Keys

By adding foreign keys, various bugs can occur, and since beginners may not be familiar with the code, it can slow down their learning process.

For example, issues can arise during migration execution or when creating test data.

Beginners might find it better to get accustomed to the process before trying to tackle this task.

How to Set Foreign Keys in Laravel

You can implement this by changing the user_details migration file as follows:

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('user_details', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('user_id')->unsigned(); // Add unsigned
            $table->string('address');
            $table->timestamps();

            // Add foreign key constraint
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::table('user_details', function (Blueprint $table) {
            $table->dropForeign(['user_id']); // Remove foreign key constraint
        });

        Schema::dropIfExists('user_details');
    }
};

Conclusion

This article summarized how to implement one-to-one relationships in Laravel.

I hope it serves as a reference for someone.

Related Articles

How to Implement One-to-Many Relationships in Laravel and Save, Display Data【hasMany】

How to Implement Many-to-One Relationships in Laravel and Save, Display Data. The Reverse of One-to-Many【belongsTo】

How to Implement Many-to-Many Relationships in Laravel and Save, Display Data.【belongsToMany】

Please Provide Feedback
We would appreciate your feedback on this article. Feel free to leave a comment on any relevant YouTube video or reach out through the contact form. Thank you!