Skip to content

Commit

Permalink
access to parent model from withDefault closure (#23334)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
salkhwlani authored and taylorotwell committed Feb 28, 2018
1 parent 5b2923e commit 9ac4664
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected function getDefaultFor(Model $parent)
$instance = $this->newRelatedInstanceFor($parent);

if (is_callable($this->withDefault)) {
return call_user_func($this->withDefault, $instance) ?: $instance;
return call_user_func($this->withDefault, $instance, $parent) ?: $instance;
}

if (is_array($this->withDefault)) {
Expand Down
20 changes: 20 additions & 0 deletions tests/Database/DatabaseEloquentHasOneTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@ public function testHasOneWithDynamicDefault()
$this->assertSame(1, $newModel->getAttribute('foreign_key'));
}

public function testHasOneWithDynamicDefaultUseParentModel()
{
$relation = $this->getRelation()->withDefault(function ($newModel, $parentModel) {
$newModel->username = $parentModel->username;
});

$this->builder->shouldReceive('first')->once()->andReturnNull();

$newModel = new EloquentHasOneModelStub;

$this->related->shouldReceive('newInstance')->once()->andReturn($newModel);

$this->assertSame($newModel, $relation->getResults());

$this->assertSame('taylor', $newModel->username);

$this->assertSame(1, $newModel->getAttribute('foreign_key'));
}

public function testHasOneWithArrayDefault()
{
$attributes = ['username' => 'taylor'];
Expand Down Expand Up @@ -191,6 +210,7 @@ protected function getRelation()
$this->builder->shouldReceive('getModel')->andReturn($this->related);
$this->parent = m::mock('Illuminate\Database\Eloquent\Model');
$this->parent->shouldReceive('getAttribute')->with('id')->andReturn(1);
$this->parent->shouldReceive('getAttribute')->with('username')->andReturn('taylor');
$this->parent->shouldReceive('getCreatedAtColumn')->andReturn('created_at');
$this->parent->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at');
$this->parent->shouldReceive('newQueryWithoutScopes')->andReturn($this->builder);
Expand Down

0 comments on commit 9ac4664

Please sign in to comment.