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.guser_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