[5.6] access to parent model from withDefault closure#23334
Conversation
Sometimes, you may wish to return default value of relations using advanced logic and condition base of parent values
This already support but not work for lazy eager loading for example
```php
// Message model
public function user()
{
return $this->belongsTo(User::class)->withDefault(function ($user) {
$user->name = $this->getAttribute('username');
$user->email = $this->getAttribute('email');
return $user;
});
}
// single record.
$message = Message::first();
$message->user->name; // return username from message model as except.
// but i we try access to user info use lazy eager loading
$messages = Message::with('user')->get();
$messages->first()->user->name; // return null
```
This PR support pass parent model to closure to make sure the parent model available in all cases.
```php
public function user()
{
return $this->belongsTo(User::class)->withDefault(function ($user, $parent) {
$user->name = $parent->getAttribute('username');
$user->email = $parent->getAttribute('email');
return $user;
});
}
```
thanks
|
@taylorotwell is there any chance we can backport this to Laravel 5.5? This PR is actually a workaround for a bug, and not a new feature. I have a But when I'm eager loading this relation from an eloquent collection, all the results are wrong. public function salary()
{
return $this->hasOne(Salary::class)->withDefault(function ($salary) {
return $salary->fill([
'currency' => $this->currency,
]);
});It works fine on single models: $userA = User::create(['currency' => 'USD']);
$userA->salary()->create(['amount' => 100, 'currency' => $userA->currency]);
$userA->salary->currency === 'USD'; // this is true
$userB = User::create(['currency' => 'EUR']);
$userB->salary->currency === 'EUR'; // this is trueBut when we eager-load eloquent collections, things are getting messy: $users = User::get()->load('salary');
$users->find($userA)->salary->currency === 'USD'; // this is true
// Here the salary currency is USD, because when we used `$this->currency` in the withDefault callback,
// `$this` was bound to the $userA, and not the matching parent user instance.
$users->find($userB)->salary->currency === 'EUR'; // this is false |
Sometimes, you may wish to return default value of relations using advanced logic and condition base of parent values
This already support but not work for lazy eager loading for example
This PR support pass parent model to closure to make sure the parent model available in all cases.
thanks