From 54dde57a2c9c5a0baedc0bea9411890dd5daf861 Mon Sep 17 00:00:00 2001 From: Harry Gulliford Date: Wed, 11 May 2022 12:25:37 +1000 Subject: [PATCH 1/2] Add test to check a factory closure attribute returning a factory is resolved --- tests/Database/DatabaseEloquentFactoryTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/Database/DatabaseEloquentFactoryTest.php b/tests/Database/DatabaseEloquentFactoryTest.php index 3f9d3d9a236a..7dbae34fe44e 100644 --- a/tests/Database/DatabaseEloquentFactoryTest.php +++ b/tests/Database/DatabaseEloquentFactoryTest.php @@ -137,6 +137,18 @@ public function test_expanded_closure_attributes_are_resolved_and_passed_to_clos $this->assertSame('taylor-options', $user->options); } + public function test_expanded_closure_attribute_returning_a_factory_is_resolved() + { + $post = FactoryTestPostFactory::new()->create([ + 'title' => 'post', + 'user_id' => fn ($attributes) => FactoryTestUserFactory::new([ + 'options' => $attributes['title'].'-options', + ]), + ]); + + $this->assertEquals('post-options', $post->user->options); + } + public function test_make_creates_unpersisted_model_instance() { $user = FactoryTestUserFactory::new()->makeOne(); From d3bbb2ce34d7cb38bd3bb97f224f4266c8898935 Mon Sep 17 00:00:00 2001 From: Harry Gulliford Date: Wed, 11 May 2022 15:39:57 +1000 Subject: [PATCH 2/2] Fix evaluation of factories and models when returned from a closure in factory definition --- src/Illuminate/Database/Eloquent/Factories/Factory.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Factories/Factory.php b/src/Illuminate/Database/Eloquent/Factories/Factory.php index 7ff36f4e7116..5c95a03d7c34 100644 --- a/src/Illuminate/Database/Eloquent/Factories/Factory.php +++ b/src/Illuminate/Database/Eloquent/Factories/Factory.php @@ -448,22 +448,22 @@ protected function parentResolvers() protected function expandAttributes(array $definition) { return collect($definition) - ->map(function ($attribute, $key) { + ->map($evaluateRelations = function ($attribute) { if ($attribute instanceof self) { $attribute = $attribute->create()->getKey(); } elseif ($attribute instanceof Model) { $attribute = $attribute->getKey(); } - $definition[$key] = $attribute; - return $attribute; }) - ->map(function ($attribute, $key) use (&$definition) { + ->map(function ($attribute, $key) use (&$definition, $evaluateRelations) { if (is_callable($attribute) && ! is_string($attribute) && ! is_array($attribute)) { $attribute = $attribute($definition); } + $attribute = $evaluateRelations($attribute); + $definition[$key] = $attribute; return $attribute;