Relationships in Models

Eloquent: Relationships - Laravel 12.x - The PHP Framework For Web Artisans

image.png

One to one relationship

Creating a one to one relationship

In order to create a one to one relationship between 2 tables, a foreignId column needs to be added to the table which holds the many side of the relationship.

<aside> 💡

The foreignId method creates an UNSIGNED BIGINT equivalent column

</aside>

<aside> 💡

The constrained method will use conventions to determine the table and column being referenced.

constrained uses the string given to foreignId which by convention should be [name-of-the-table]-[name-of-the-column] .

If conventions aren’t respected, constraint should be explicitly created:

$table->foreignId('user_id')->constrained(
    table: 'users', indexName: 'posts_user_id'
);

</aside>

<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('phones', function (Blueprint $table) {
            $table->id();
            $table->string(column: 'number');
            **$table->foreignId('user_id')->constrained();**
            $table->timestamps();
        });
    }

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

<aside> 💡

In a one to one relationships, a belongsTo method should be implemented in the child model which signifies the model belongs to a single instance of another model.

</aside>

<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;

class Phone extends Model
{
    protected $fillable = ['number','user_id'];
    public function user(): **BelongsTo** 
    {
        **return $this->belongsTo(User::class);**
    }
}

<aside> 💡

In a one to one relationships, a hasOne method should be implemented in the parent model which signifies the model owning exactly one of the related model.

</aside>

<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Foundation\\Auth\\User as Authenticatable;
use Illuminate\\Notifications\\Notifiable;
use Illuminate\\Database\\Eloquent\\Relations\\HasOne;

class User extends Authenticatable
{
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    public function phone(): **HasOne**
    {
        **return $this->hasOne(Phone::class);**
    }

}

Loading participants in a relationship

<aside> ⚠️

In order to use load() and with() methods in a query, the relations should be already defined on the model that the query starts with

</aside>

<aside> 💡

Eager loading retrieves the relationship data at the same time as the primary data in a single query by joining the tables.

$users = User::with('phones')->get(); // all() won't work here !

</aside>

<aside> 💡

Lazy loading retrieves the relationship data only when it is accessed. It can lead to multiple database queries.

$users = User::all();

foreach ($users as $user) {
    $phone = $user->phone;
}

Using load() method:

$users::all()->load('phone');

</aside>

Accessing relationships