Skip to content

Commit 03e7fd9

Browse files
[12.x] Adds set relation attribute using Model.
1 parent 8f8235f commit 03e7fd9

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php

+33
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Brick\Math\RoundingMode;
99
use Carbon\CarbonImmutable;
1010
use Carbon\CarbonInterface;
11+
use Closure;
1112
use DateTimeImmutable;
1213
use DateTimeInterface;
1314
use Illuminate\Contracts\Database\Eloquent\Castable;
@@ -24,6 +25,8 @@
2425
use Illuminate\Database\Eloquent\InvalidCastException;
2526
use Illuminate\Database\Eloquent\JsonEncodingException;
2627
use Illuminate\Database\Eloquent\MissingAttributeException;
28+
use Illuminate\Database\Eloquent\Model;
29+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
2730
use Illuminate\Database\Eloquent\Relations\Relation;
2831
use Illuminate\Database\LazyLoadingViolationException;
2932
use Illuminate\Support\Arr;
@@ -581,6 +584,32 @@ public function isRelation($key)
581584
$this->relationResolver(static::class, $key);
582585
}
583586

587+
/**
588+
* Determine if the given relation name is a BelongsTo relation.
589+
*
590+
* @param string $key
591+
* @param mixed $value
592+
* @return bool
593+
*/
594+
public function isBelongsToRelation($key, $value)
595+
{
596+
return $value instanceof Model
597+
&& $this->isRelation($key)
598+
&& $this->{$key}() instanceof BelongsTo;
599+
}
600+
601+
/**
602+
* Associates or attaches a model relation using the appropriate method relation.
603+
*
604+
* @param string $relation
605+
* @param \Illuminate\Database\Eloquent\Model $instance
606+
* @return $this
607+
*/
608+
protected function fillBelongsToRelation($relation, $instance)
609+
{
610+
return $this->$relation()->associate($instance);
611+
}
612+
584613
/**
585614
* Handle a lazy loading violation.
586615
*
@@ -1074,6 +1103,10 @@ public function setAttribute($key, $value)
10741103
$value = $this->castAttributeAsHashedString($key, $value);
10751104
}
10761105

1106+
if ($this->isBelongsToRelation($key, $value)) {
1107+
return $this->fillBelongsToRelation($key, $value);
1108+
}
1109+
10771110
$this->attributes[$key] = $value;
10781111

10791112
return $this;

tests/Database/DatabaseEloquentModelTest.php

+49
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,55 @@ public function testFillable()
15751575
$this->assertSame('bar', $model->age);
15761576
}
15771577

1578+
public function testFillableWithBelongsToRelation()
1579+
{
1580+
$model = new EloquentModelStub;
1581+
$this->addMockConnection($model);
1582+
1583+
$model->fillable(['name', 'age']);
1584+
$relation = new EloquentModelSaveStub();
1585+
$relation->id = 10;
1586+
1587+
$model->fill(['name' => 'foo', 'age' => 'bar', 'belongsToStub' => $relation, 'morphToStub' => $relation]);
1588+
1589+
$this->assertNull($model->belongs_to_stub_id);
1590+
$this->assertNull($model->morph_to_stub_id);
1591+
1592+
$model->fillable(['name', 'age', 'belongsToStub', 'morphToStub']);
1593+
$model->fill(['name' => 'foo', 'age' => 'bar', 'belongsToStub' => $relation, 'morphToStub' => $relation]);
1594+
1595+
$this->assertSame('foo', $model->name);
1596+
$this->assertSame('bar', $model->age);
1597+
$this->assertSame(10, $model->belongs_to_stub_id);
1598+
$this->assertSame(10, $model->morph_to_stub_id);
1599+
$this->assertSame(EloquentModelSaveStub::class, $model->morph_to_stub_type);
1600+
$this->assertSAme($relation, $model->getRelation('belongsToStub'));
1601+
$this->assertSAme($relation, $model->getRelation('morphToStub'));
1602+
1603+
$this->assertSame('foo', $model->fill(['belongsToStub' => 'foo'])->belongsToStub);
1604+
}
1605+
1606+
public function testFillableWithBelongsToRelationNotFillable()
1607+
{
1608+
$model = new EloquentModelStub;
1609+
$model->fillable(['name', 'age', 'belongsToStub']);
1610+
1611+
$model->fill(['belongsToStub' => 'foo']);
1612+
1613+
$this->assertNull($model->foo);
1614+
1615+
$model = new EloquentModelWithWhereHasStub;
1616+
$this->addMockConnection($model);
1617+
$model->fillable(['name', 'foo']);
1618+
1619+
$relation = new EloquentModelSaveStub();
1620+
1621+
$model->fill(['foo' => $relation]);
1622+
1623+
$this->assertNull($model->getRelation('foo'));
1624+
$this->assertSame($relation, $model->getAttribute('foo'));
1625+
}
1626+
15781627
public function testQualifyColumn()
15791628
{
15801629
$model = new EloquentModelStub;

0 commit comments

Comments
 (0)