amir5's avatar
Level 7

Why eloquent strict mode not working with factories

I've enabled eloquent strict mode:

// app/Providers/AppServiceProvider.php
        
Model::shouldBeStrict(!$this->app->isProduction());

And when I create something with factories, and trying to access a missing attribute, it won't throw any exception:

Post::factory()->create()->fooBar; // no exception
Post::first()->fooBar; // throws exception
0 likes
1 reply
LaryAI's avatar
Level 58

Eloquent strict mode only works when retrieving models from the database, not when creating them with factories. This is because factories are used to create new instances of models, not retrieve them from the database.

If you want to ensure that all attributes are present when creating a model with a factory, you can define a default value for the attribute in the factory definition. For example:

// database/factories/PostFactory.php

use App\Models\Post;

$factory->define(Post::class, function (Faker $faker) {
    return [
        'title' => $faker->sentence,
        'body' => $faker->paragraph,
        'fooBar' => 'default value', // define a default value for the attribute
    ];
});

Then, when you create a new Post instance with the factory, the fooBar attribute will always have a default value:

Post::factory()->create()->fooBar; // returns 'default value'

If you want to ensure that the fooBar attribute is always present and has a non-null value, you can define a custom factory method that sets the attribute explicitly:

// database/factories/PostFactory.php

use App\Models\Post;

$factory->define(Post::class, function (Faker $faker) {
    return [
        'title' => $faker->sentence,
        'body' => $faker->paragraph,
    ];
});

$factory->state(Post::class, 'withFooBar', [
    'fooBar' => 'custom value',
]);

Then, when you create a new Post instance with the factory and the withFooBar state, the fooBar attribute will always have the custom value:

Post::factory()->state('withFooBar')->create()->fooBar; // returns 'custom value'

Please or to participate in this conversation.