Right now it appears that using Closure factory states alongside Faker does not work, this is because the Closure is created in another instance of the factory then where it is eventually invoked, so when it is invoked $this->faker still references the old instance's faker (which, depending on the situation, may or may not be null). So instead attributes created via faker this way will be null.
composer create-project laravel/laravel:dev-develop public function foo()
{
return $this->state(fn () => [
'name' => $this->faker->name,
]);
}
User::factory()->foo()->make()I was able to get it working by adding $state = $state->bindTo($this); within the reduce callback in Factory::getRawAttributes(), this works because $this->faker = $this->withFaker() is called right before the states are resolved, but I don't know what further implications this has.
Thanks! We've fixed this.
Is it just me or is this still broken?
laravel new testProject (Laravel 8.0.0)UserFactory.phppublic function foo()
{
return $this->state([
'name' => $this->faker->name,
]);
}
User::factory()->foo()->make()PHP Notice: Trying to get property 'name' of non-objectdd($this->faker); returns null@axlon @driesvints
(note the example method here is not returning a closure, but an array as demonstrated in the docs)
@drbyte could it be that you're using a unit test where the framework isn't booted?
@driesvints no, it's a proper FeatureTest which properly extends TestCase
Here's a blank repo with a commit showing how to reproduce it:
https://github.com/drbyte/withFaker-bug/commit/45442006ed35c394a23f2372cc5b8012f5463f6d
@drbyte its because your state is not within a closure, when you use it like this the state will be resolved as soon as you call the method, before faker is initialised
Changing it to the snippet below should fix it:
public function male()
{
return $this->state(fn () => [
'name' => $this->faker->firstNameMale,
]);
}
Edit (as I didn't read your first comment initially) : I haven't checked the docs yet, so I don't know if it shows an example without a Closure but AFAIK it won't work without a closure unless you manually instantiate faker on the factory instance (which I wouldn't recommend because of the way factories work internally)
Thanks. My brain was treating it as a regular class, but of course it's not. 馃槃
The docs don't mention it, but I've submitted a PR. https://github.com/laravel/docs/pull/6329/files
Most helpful comment
Thanks. My brain was treating it as a regular class, but of course it's not. 馃槃
The docs don't mention it, but I've submitted a PR. https://github.com/laravel/docs/pull/6329/files