Home > Enterprise >  Laravel / Eloquent relationship terminology
Laravel / Eloquent relationship terminology

Time:11-19

I have no idea what all of the terminology means in the Laravel/Eloquent docs for relationships like hasOne or belongsTo.

The hasOne class has the properties $parent, $related, $foreignKey, and $localKey among others.

The belongsTo class has the properties $parent, $related, $child, $foreignKey, and $ownerKey among others.

I wish I had a cheat sheet that had example relationships like

Given a one to one relationship between users and phones:

user hasOne phone.
phone belongsTo user

hasOne class properties:
$parent = a
$related = b
$foreignKey = c
$localKey = d
... maybe more hasOne properties here

belongsTo class properties:
$parent = a
$related = b
$child = c
$foreignKey = d
$ownerKey = e
... maybe more belongsTo properties here

Except with a, b, c, d, etc filled in.

I'd love have these kinds of examples for all relationship types. hasMany class properties and belongsToMany class properties in one to many and many to many relationships, etc. Every combination.

The following quote (which is probably wrong) from my notes highlights a confusion I have:

"if a hasOne b or a hasMany b: a is called the parent model and b is called the related model, but I think b is also called the child model, so idk." - I'm pretty sure this quote is wrong, but I wish I knew the distinction between the different terms like child model and related model, etc.

CodePudding user response:

Eloquent's APIs are harder to understand once you're trying to fill in all the variables and what they do. I'm going to re-use Laravel's example of User having phones as you used it with all of the given code filled in.

Given a User model with an id and a Phone model with an id and a user_id, the two functions would look like this:

User.php:

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

In which case,

  • $parent is the current User model (e.g User id 1)
  • $related is the phone that this user has (e.g Phone id 1)
  • $foreignKey is the key you have inside your Phone model (e.g user_id)
  • $local_key is the key that you have in your local / current model which is User in this case.

the same goes for the reverse:

Phone.php

public function user()
{
    return $this->belongsTo(User::class, 'user_id', 'id');
}

the same above is still true except now you have owner_key instead of local_key, it still refers to the key in the original / parent model.

I have to admit that I'm not sure what the $child property does though I wouldn't worry about it if I was beginning my Laravel journey since there's no "end-user" use case that I've seen for it since Laravel 5.x.

CodePudding user response:

--- TLDR:---

relationship = $user->phone()
this is a HasOne relationship / instance.

parent : {"id":1,"name":"Bernice Kautzer DVM","email":"[email protected]","email_verified_at":"2022-11-18T21:58:52.000000Z","created_at":"2022-11-18T21:58:52.000000Z","updated_at":"2022-11-18T21:58:52.000000Z"} // ie $parent equals the User instance
related : []
foreignKey : phones.user_id
localKey : id

---------

relationship = $phone->user()
This is a BelongsTo relationship / instance.

parent : {"id":4,"created_at":"2022-11-18T21:58:52.000000Z","updated_at":"2022-11-18T21:58:52.000000Z","user_id":1}
related : []
child : {"id":4,"created_at":"2022-11-18T21:58:52.000000Z","updated_at":"2022-11-18T21:58:52.000000Z","user_id":1} // ie $parent equals the Phone instance
foreignKey : user_id
ownerKey : id

--- END TLDR ---

The source code that I used to do this test, for anyone who is interested:

When I do:

   $user = User::first();
   $usersPhone = $user->phone();
   $parent = $this->accessProtected($usersPhone, 'parent');
   $related = $this->accessProtected($usersPhone, 'related');
   $foreignKey = $this->accessProtected($usersPhone, 'foreignKey');
   $localKey = $this->accessProtected($usersPhone, 'localKey');



   echo "relationship = \$user->phone()" . PHP_EOL;
   echo "is relationship HasOne? : " . $usersPhone instanceOf HasOne . PHP_EOL;
   echo "is relationship BelongsTo? : " . $usersPhone instanceOf BelongsTo . PHP_EOL;
   echo "parent : " . $parent . PHP_EOL;
   echo "related : " . $related . PHP_EOL;
   echo "foreignKey : " . $foreignKey . PHP_EOL;
   echo "localKey : " . $localKey . PHP_EOL;
   echo "---------" . PHP_EOL;
I get 
relationship = $user->phone()
is relationship HasOne? : 1
is relationship BelongsTo? : 
parent : {"id":1,"name":"Bernice Kautzer DVM","email":"[email protected]","email_verified_at":"2022-11-18T21:58:52.000000Z","created_at":"2022-11-18T21:58:52.000000Z","updated_at":"2022-11-18T21:58:52.000000Z"}
related : []
foreignKey : phones.user_id
localKey : id

When I do: $phone = Phone::find(4); $phonesUser = $phone->user(); $parent = $this->accessProtected($phonesUser, 'parent'); $related = $this->accessProtected($phonesUser, 'related'); $child = $this->accessProtected($phonesUser, 'child'); $foreignKey = $this->accessProtected($phonesUser, 'foreignKey'); $ownerKey = $this->accessProtected($phonesUser, 'ownerKey');

    echo "relationship = \$phone->user()" . PHP_EOL;
    echo  "is relationship HasOne? : " . $phonesUser instanceOf HasOne . PHP_EOL;
    echo  "is relationship BelongsTo? : " . $phonesUser instanceOf BelongsTo . PHP_EOL;
    echo "parent : " . $parent . PHP_EOL;
    echo "related : " . $related . PHP_EOL;
    echo "child : " . $child . PHP_EOL;
    echo "foreignKey : " . $foreignKey . PHP_EOL;
    echo "ownerKey : " . $ownerKey . PHP_EOL;
    
I get:
relationship = $phone->user()
is relationship HasOne? : 
is relationship BelongsTo? : 1
parent : {"id":4,"created_at":"2022-11-18T21:58:52.000000Z","updated_at":"2022-11-18T21:58:52.000000Z","user_id":1}
related : []
child : {"id":4,"created_at":"2022-11-18T21:58:52.000000Z","updated_at":"2022-11-18T21:58:52.000000Z","user_id":1}
foreignKey : user_id
ownerKey : id
  • Related