phplaravellaravel-seedinglaravel-events

laravel userstamps without disturbing the database seeding


Is there any way to automate the filling of a created_by column without the use of observers, but keeping my controllers clean? I don't want to use observers because when I try to seed my database, errors happen.

The way I'm doing now:

class ClientObserver
{
    public function creating(Client $client)
    {
        $client->author()->associate(auth()->user());
    }
}

and it works for creating clients through the app when I register into a service provider's boot, but when I use artisan to seed the database with that factory:

$factory->define(Client::class, function (Faker $faker) {
    return [
        'name' => $faker->company,
        'description' => $faker->paragraph,
        'address' => $faker->address,
        'created_by' => User::all()->random()->id,
    ];
});

I get this error:

Integrity constraint violation: 19 NOT NULL constraint failed: clients.created_by

because the "creating" event is triggered and the observer acts. Is there at least some way to stop the observer from taking action?

Any help will be welcome. Thank you :)


Solution

  • In the seeder, set and unset a config value before and after the factory.

    // DatabaseSeeder.php
    public function run()
    {
        config()->set('seeding', true);
    
        factory(App\Client::class, 50)->create();
    
        config()->set('seeding', false);
    }
    

    You can avoid having an Observer by overriding the boot method of your model. Check for the config value and set the user as required.

    // Client.php
    protected static function boot() {
        parent::boot();
    
        static::creating(function($client) {
            if (config()->get('seeding') === true)
                auth()->setUser(User::inRandomOrder()->first());
            $client->author()->associate(auth()->user());
        });
    }