Skip to content

Commit 0dba49d

Browse files
[12.x] Feat: ability to explicitly exclude factory relationships (laravel#56396)
* feat: ability to explicitly exclude factory relationships * chore: style * Update Factory.php * fix: fix resetting $excludeRelationships state when creating new instance * feat: ability to exclude factory relationships by attribute name * fix: drop unused $definition --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent d70e372 commit 0dba49d

File tree

2 files changed

+50
-5
lines changed

2 files changed

+50
-5
lines changed

src/Illuminate/Database/Eloquent/Factories/Factory.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ abstract class Factory
9191
*/
9292
protected $expandRelationships = true;
9393

94+
/**
95+
* The relationships that should not be automatically created.
96+
*
97+
* @var array
98+
*/
99+
protected $excludeRelationships = [];
100+
94101
/**
95102
* The name of the database connection that will be used to create the models.
96103
*
@@ -152,6 +159,7 @@ abstract class Factory
152159
* @param string|null $connection
153160
* @param \Illuminate\Support\Collection|null $recycle
154161
* @param bool|null $expandRelationships
162+
* @param array $excludeRelationships
155163
*/
156164
public function __construct(
157165
$count = null,
@@ -162,7 +170,8 @@ public function __construct(
162170
?Collection $afterCreating = null,
163171
$connection = null,
164172
?Collection $recycle = null,
165-
?bool $expandRelationships = null
173+
?bool $expandRelationships = null,
174+
array $excludeRelationships = [],
166175
) {
167176
$this->count = $count;
168177
$this->states = $states ?? new Collection;
@@ -174,6 +183,7 @@ public function __construct(
174183
$this->recycle = $recycle ?? new Collection;
175184
$this->faker = $this->withFaker();
176185
$this->expandRelationships = $expandRelationships ?? self::$expandRelationshipsByDefault;
186+
$this->excludeRelationships = $excludeRelationships;
177187
}
178188

179189
/**
@@ -505,9 +515,12 @@ protected function parentResolvers()
505515
protected function expandAttributes(array $definition)
506516
{
507517
return (new Collection($definition))
508-
->map($evaluateRelations = function ($attribute) {
518+
->map($evaluateRelations = function ($attribute, $key) {
509519
if (! $this->expandRelationships && $attribute instanceof self) {
510520
$attribute = null;
521+
} elseif ($attribute instanceof self &&
522+
array_intersect([$attribute->modelName(), $key], $this->excludeRelationships)) {
523+
$attribute = null;
511524
} elseif ($attribute instanceof self) {
512525
$attribute = $this->getRandomRecycledModel($attribute->modelName())?->getKey()
513526
?? $attribute->recycle($this->recycle)->create()->getKey();
@@ -522,7 +535,7 @@ protected function expandAttributes(array $definition)
522535
$attribute = $attribute($definition);
523536
}
524537

525-
$attribute = $evaluateRelations($attribute);
538+
$attribute = $evaluateRelations($attribute, $key);
526539

527540
$definition[$key] = $attribute;
528541

@@ -774,11 +787,12 @@ public function count(?int $count)
774787
/**
775788
* Indicate that related parent models should not be created.
776789
*
790+
* @param array<string|class-string<Model>> $parents
777791
* @return static
778792
*/
779-
public function withoutParents()
793+
public function withoutParents($parents = [])
780794
{
781-
return $this->newInstance(['expandRelationships' => false]);
795+
return $this->newInstance(! $parents ? ['expandRelationships' => false] : ['excludeRelationships' => $parents]);
782796
}
783797

784798
/**
@@ -820,6 +834,7 @@ protected function newInstance(array $arguments = [])
820834
'connection' => $this->connection,
821835
'recycle' => $this->recycle,
822836
'expandRelationships' => $this->expandRelationships,
837+
'excludeRelationships' => $this->excludeRelationships,
823838
], $arguments)));
824839
}
825840

tests/Database/DatabaseEloquentFactoryTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,36 @@ public function test_can_disable_relationships()
832832
$this->assertNull($post->user_id);
833833
}
834834

835+
public function test_can_disable_relationships_explicitly_by_model_name()
836+
{
837+
$comment = FactoryTestCommentFactory::new()
838+
->withoutParents([FactoryTestUser::class])
839+
->make();
840+
841+
$this->assertNull($comment->user_id);
842+
$this->assertNotNull($comment->commentable->id);
843+
}
844+
845+
public function test_can_disable_relationships_explicitly_by_attribute_name()
846+
{
847+
$comment = FactoryTestCommentFactory::new()
848+
->withoutParents(['user_id'])
849+
->make();
850+
851+
$this->assertNull($comment->user_id);
852+
$this->assertNotNull($comment->commentable->id);
853+
}
854+
855+
public function test_can_disable_relationships_explicitly_by_both_attribute_name_and_model_name()
856+
{
857+
$comment = FactoryTestCommentFactory::new()
858+
->withoutParents(['user_id', FactoryTestPost::class])
859+
->make();
860+
861+
$this->assertNull($comment->user_id);
862+
$this->assertNull($comment->commentable->id);
863+
}
864+
835865
public function test_can_default_to_without_parents()
836866
{
837867
FactoryTestPostFactory::dontExpandRelationshipsByDefault();

0 commit comments

Comments
 (0)