Skip to content

Commit ff00aa9

Browse files
committed
Add withDefault to MorphOne relations.
1 parent 748831a commit ff00aa9

File tree

4 files changed

+103
-90
lines changed

4 files changed

+103
-90
lines changed

src/Illuminate/Database/Eloquent/Relations/BelongsTo.php

+13-46
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,11 @@
55
use Illuminate\Database\Eloquent\Model;
66
use Illuminate\Database\Eloquent\Builder;
77
use Illuminate\Database\Eloquent\Collection;
8+
use Illuminate\Database\Eloquent\Relations\Concerns\HasDefault;
89

910
class BelongsTo extends Relation
1011
{
11-
/**
12-
* Indicates if a default model instance should be used.
13-
*
14-
* Alternatively, may be a Closure or array.
15-
*
16-
* @var \Closure|array|bool
17-
*/
18-
protected $withDefault;
12+
use HasDefault;
1913

2014
/**
2115
* The child model instance of the relation.
@@ -164,31 +158,6 @@ public function initRelation(array $models, $relation)
164158
return $models;
165159
}
166160

167-
/**
168-
* Get the default value for this relation.
169-
*
170-
* @param \Illuminate\Database\Eloquent\Model $model
171-
* @return \Illuminate\Database\Eloquent\Model|null
172-
*/
173-
protected function getDefaultFor(Model $model)
174-
{
175-
if (! $this->withDefault) {
176-
return;
177-
}
178-
179-
$instance = $this->related->newInstance();
180-
181-
if (is_callable($this->withDefault)) {
182-
return call_user_func($this->withDefault, $instance) ?: $instance;
183-
}
184-
185-
if (is_array($this->withDefault)) {
186-
$instance->forceFill($this->withDefault);
187-
}
188-
189-
return $instance;
190-
}
191-
192161
/**
193162
* Match the eagerly loaded results to their parents.
194163
*
@@ -327,19 +296,6 @@ protected function relationHasIncrementingId()
327296
$this->related->getKeyType() === 'int';
328297
}
329298

330-
/**
331-
* Return a new model instance in case the relationship does not exist.
332-
*
333-
* @param \Closure|array|bool $callback
334-
* @return $this
335-
*/
336-
public function withDefault($callback = true)
337-
{
338-
$this->withDefault = $callback;
339-
340-
return $this;
341-
}
342-
343299
/**
344300
* Get the foreign key of the relationship.
345301
*
@@ -389,4 +345,15 @@ public function getRelation()
389345
{
390346
return $this->relation;
391347
}
348+
349+
/**
350+
* Make a new related instance for the given model.
351+
*
352+
* @param \Illuminate\Database\Eloquent\Model $parent
353+
* @return \Illuminate\Database\Eloquent\Model
354+
*/
355+
protected function newRelatedInstanceFor(Model $parent)
356+
{
357+
return $this->related->newInstance();
358+
}
392359
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace Illuminate\Database\Eloquent\Relations\Concerns;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
trait HasDefault
8+
{
9+
/**
10+
* Indicates if a default model instance should be used.
11+
*
12+
* Alternatively, may be a Closure or array.
13+
*
14+
* @var \Closure|array|bool
15+
*/
16+
protected $withDefault;
17+
18+
/**
19+
* Return a new model instance in case the relationship does not exist.
20+
*
21+
* @param \Closure|array|bool $callback
22+
* @return $this
23+
*/
24+
public function withDefault($callback = true)
25+
{
26+
$this->withDefault = $callback;
27+
28+
return $this;
29+
}
30+
31+
/**
32+
* Get the default value for this relation.
33+
*
34+
* @param \Illuminate\Database\Eloquent\Model $parent
35+
* @return \Illuminate\Database\Eloquent\Model|null
36+
*/
37+
protected function getDefaultFor(Model $parent)
38+
{
39+
if (! $this->withDefault) {
40+
return;
41+
}
42+
43+
$instance = $this->newRelatedInstanceFor($parent);
44+
45+
if (is_callable($this->withDefault)) {
46+
return call_user_func($this->withDefault, $instance) ?: $instance;
47+
}
48+
49+
if (is_array($this->withDefault)) {
50+
$instance->forceFill($this->withDefault);
51+
}
52+
53+
return $instance;
54+
}
55+
56+
/**
57+
* Make a new related instance for the given model.
58+
*
59+
* @param \Illuminate\Database\Eloquent\Model $parent
60+
* @return \Illuminate\Database\Eloquent\Model
61+
*/
62+
abstract protected function newRelatedInstanceFor(Model $parent);
63+
}

src/Illuminate/Database/Eloquent/Relations/HasOne.php

+8-42
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,11 @@
44

55
use Illuminate\Database\Eloquent\Model;
66
use Illuminate\Database\Eloquent\Collection;
7+
use Illuminate\Database\Eloquent\Relations\Concerns\HasDefault;
78

89
class HasOne extends HasOneOrMany
910
{
10-
/**
11-
* Indicates if a default model instance should be used.
12-
*
13-
* Alternatively, may be a Closure or array.
14-
*
15-
* @var \Closure|array|bool
16-
*/
17-
protected $withDefault;
11+
use HasDefault;
1812

1913
/**
2014
* Get the results of the relationship.
@@ -42,33 +36,6 @@ public function initRelation(array $models, $relation)
4236
return $models;
4337
}
4438

45-
/**
46-
* Get the default value for this relation.
47-
*
48-
* @param \Illuminate\Database\Eloquent\Model $model
49-
* @return \Illuminate\Database\Eloquent\Model|null
50-
*/
51-
protected function getDefaultFor(Model $model)
52-
{
53-
if (! $this->withDefault) {
54-
return;
55-
}
56-
57-
$instance = $this->related->newInstance()->setAttribute(
58-
$this->getForeignKeyName(), $model->getAttribute($this->localKey)
59-
);
60-
61-
if (is_callable($this->withDefault)) {
62-
return call_user_func($this->withDefault, $instance) ?: $instance;
63-
}
64-
65-
if (is_array($this->withDefault)) {
66-
$instance->forceFill($this->withDefault);
67-
}
68-
69-
return $instance;
70-
}
71-
7239
/**
7340
* Match the eagerly loaded results to their parents.
7441
*
@@ -83,15 +50,14 @@ public function match(array $models, Collection $results, $relation)
8350
}
8451

8552
/**
86-
* Return a new model instance in case the relationship does not exist.
53+
* Make a new related instance for the given model.
8754
*
88-
* @param \Closure|array|bool $callback
89-
* @return $this
55+
* @param \Illuminate\Database\Eloquent\Model $parent
56+
* @return \Illuminate\Database\Eloquent\Model
9057
*/
91-
public function withDefault($callback = true)
58+
public function newRelatedInstanceFor(Model $parent)
9259
{
93-
$this->withDefault = $callback;
94-
95-
return $this;
60+
return $this->related->newInstance()
61+
->setAttribute($this->getForeignKeyName(), $parent->{$this->localKey});
9662
}
9763
}

src/Illuminate/Database/Eloquent/Relations/MorphOne.php

+19-2
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@
22

33
namespace Illuminate\Database\Eloquent\Relations;
44

5+
use Illuminate\Database\Eloquent\Model;
56
use Illuminate\Database\Eloquent\Collection;
7+
use Illuminate\Database\Eloquent\Relations\Concerns\HasDefault;
68

79
class MorphOne extends MorphOneOrMany
810
{
11+
use HasDefault;
12+
913
/**
1014
* Get the results of the relationship.
1115
*
1216
* @return mixed
1317
*/
1418
public function getResults()
1519
{
16-
return $this->query->first();
20+
return $this->query->first() ?: $this->getDefaultFor($this->parent);
1721
}
1822

1923
/**
@@ -26,7 +30,7 @@ public function getResults()
2630
public function initRelation(array $models, $relation)
2731
{
2832
foreach ($models as $model) {
29-
$model->setRelation($relation, null);
33+
$model->setRelation($relation, $this->getDefaultFor($model));
3034
}
3135

3236
return $models;
@@ -44,4 +48,17 @@ public function match(array $models, Collection $results, $relation)
4448
{
4549
return $this->matchOne($models, $results, $relation);
4650
}
51+
52+
/**
53+
* Make a new related instance for the given model.
54+
*
55+
* @param \Illuminate\Database\Eloquent\Model $parent
56+
* @return \Illuminate\Database\Eloquent\Model
57+
*/
58+
public function newRelatedInstanceFor(Model $parent)
59+
{
60+
return $this->related->newInstance()
61+
->setAttribute($this->getForeignKeyName(), $parent->{$this->localKey})
62+
->setAttribute($this->getMorphType(), $this->morphClass);
63+
}
4764
}

0 commit comments

Comments
 (0)