Laravel 9 One To One | HasOne Eloquent Relationship Tutorial

https://www.laravelia.com/post/laravel-one-to-onehasone-eloquent-relationship-tutorial

In a relational database management system, you know that database tables are often related to one another. For example, a company may have many employees or an order could be related to the user who placed it. Laravel eloquent makes managing and working with these relationships very convenient. Laravel provides many relationships and in this tutorial, we will see how we handle one to one or we can call this hasOne eloquent relationship.

In this Laravel 9 one to one relationship example tutorial, I am going to use the User and Phone concept. Suppose, A user may have one phone and a phone may have one user. Let's see how we can define Laravel's one to one relationship.

Eloquent relationships are defined as methods in your Eloquent model classes. We can use the hasOne() method to define one to one relationships and the first argument passed to the hasOne method is the name of the related model class.

Assume that one user may have one Phone. So we can define this relationship like this:

C:\xampp\htdocs\wayarmy\routes\web.php

<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TestController as TestController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
    return view('welcome');
});
Route::get('test/{id}', [TestController::class,'index'])->name('index');
Route::get('test2/{id}', [TestController::class,'index2'])->name('index2');

C:\xampp\htdocs\wayarmy\database\factories\UserFactory.php

<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory
{
  protected $model = User::class;
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition()
  {
    return [
      'name' => $this->faker->name()
    ];
  }
}

C:\xampp\htdocs\wayarmy\database\factories\PhoneFactory.php

<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Phone;
class PhoneFactory extends Factory
{
  protected $model = Phone::class;
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition()
  {
    return [
      "user_id" => $this->faker->unique()->numberBetween(1, 10),
      "phone" => $this->faker->phoneNumber()
    ];
  }
}

C:\xampp\htdocs\wayarmy\database\seeders\DatabaseSeeder.php

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Phone;
class DatabaseSeeder extends Seeder
{
  /**
   * Seed the application's database.
   *
   * @return void
   */
  public function run()
  {
    User::factory(10)->create();
    Phone::factory(10)->create();
  }
}
p

C:\xampp\htdocs\wayarmy\app\Models\User.php

<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Carbon\Carbon;
use Collective\Html\Eloquent\FormAccessible;
class User extends Authenticatable
{
  use HasApiTokens, HasFactory, Notifiable, FormAccessible;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  public $timestamps  = false;
  protected $fillable = [
    'name'
  ];
  public function phone() {
    return $this->hasOne(Phone::class,'user_id','id');
  }
}

C:\xampp\htdocs\wayarmy\app\Models\Phone.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Phone extends Model
{
  use HasFactory;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'user_id',
    'phone'
  ];
  public $timestamps  = false;
  public function user()
  {
    return $this->belongsTo(User::class);
  }
}

C:\xampp\htdocs\wayarmy\app\Http\Controllers\TestController.php

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Models\Phone;
use Illuminate\Http\Request;
class TestController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index($id)
  {
    $user = User::find($id);
    /**
     * Get the phone associated with the user.
     */
    $phone = $user->phone;
    dd($phone->phone);
  }
  public function index2($id)
  {
    $phone = Phone::find($id);
    /**
     * Get the phone associated with the user.
     */
    $name = $phone->user;
    dd($name->name);
  }
}

C:\xampp\htdocs\wayarmy\database\migrations\2022_11_17_154429_create_phones_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePhonesTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('phones', function (Blueprint $table) {
      $table->id();
      $table->integer('user_id');
      $table->string('phone');
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('phones');
  }
}

C:\xampp\htdocs\wayarmy\database\migrations\2014_10_12_000000_create_users_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('users', function (Blueprint $table) {
      $table->id();
      $table->string('name');
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('users');
  }
}

In a relational database management system, you know that database tables are often related to one another. For example, a company may have many employees or an order could be related to the user who placed it. Laravel eloquent makes managing and working with these relationships very convenient. Laravel provides many relationships and in this tutorial, we will see how we handle one to one or we can call this hasOne eloquent relationship.

In this Laravel 9 one to one relationship example tutorial, I am going to use the User and Phone concept. Suppose, A user may have one phone and a phone may have one user. Let's see how we can define Laravel's one to one relationship.

Eloquent relationships are defined as methods in your Eloquent model classes. We can use the hasOne() method to define one to one relationships and the first argument passed to the hasOne method is the name of the related model class.

Assume that one user may have one Phone. So we can define this relationship like this:

app/Models/User.php

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
    /**
     * Get the phone associated with the user.
     */
    public function phone()
    {
        // $this->hasOne(Model::class,'foreign_key','local_key');
        // remember, foreign_key & local_key are optional

        return $this->hasOne(Phone::class,'user_id','id');
    }
}

PHPCopy

Now we can fetch every user's phone information from the controller like:

App\Http\Controllers\TestController.php

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;

class TestController extends Controller
{
    public function index($id)
    {   
        $user = User::find($id);

        /**
         * Get the phone associated with the user.
         */
        $user->phone;
    }
}

PHPCopy

Defining Inverse Relationship of hasOne

Now we know how to define hasOne or one to one relationship. Now we will see how we can define the inverse relationship of hasOne. Let's define a relationship on the Phone model that will let us access the user that owns his/her phone. We can define the inverse of a hasOne relationship using the belongsTo method like:

app/Models/Phone.php

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Phone extends Model
{
    /**
     * Get the user that owns the phone.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

PHPCopy

Read also: Laravel 9 Throttle Rate Limiters Middleware Example

Here we can also pass fereign_key and local_key like below:

/**
 * Get the user that owns the phone.
 */
public function user()
{
    return $this->belongsTo(User::class, 'foreign_key', 'owner_key');
}

PHPCopy

Now we can also fetch user like:

App\Http\Controllers\TestController.php

<?php

namespace App\Http\Controllers;

use App\Models\Phone;
use Illuminate\Http\Request;

class TestController extends Controller
{
    public function index($id)
    {   
        $phone = Phone::find($id);
        $phone->user;
    }
}

Last updated