1

In Laravel 8, when I run a factory()->create() on a model that has a __construct, this code :

Route::get('/test', function (){
    $doc = ClientDocument::factory()->create();
});

fails :

"SQLSTATE[HY000]: General error: 1364 Field 'filename' doesn't have a default value (SQL: insert into `client_documents` (`updated_at`, `created_at`) values (2021-11-16 12:45:20, 2021-11-16 12:45:20))"

If I remove the __construct, the factory runs fine and saves to the database... What am I missing here? Thanks!

MODEL

class ClientDocument extends Model
{
    use HasFactory;

    protected $connection = 'mysql';

    protected $fillable = ['filename'];
    protected $locale;

    public function __construct() {
        // SET THE LANGUAGE
        if ( auth()->user() ) {
             $this->locale = auth()->user()->locale;
        } else {
             $this->locale = 'en';
        }
    }
}

FACTORY

class ClientDocumentFactory extends Factory
{
    public function definition()
    {
        $user = User::factory()->create();
        $client = $user->createNewClientFile();

        return [
            'filename'  => $this->faker->lexify('????????'),
        ];
    }
}

MIGRATION

class CreateClientDocumentsTable extends Migration
{
    public function up()
    {
        Schema::create('client_documents', function (Blueprint $table) {
            $table->id();
            $table->string('filename');
            $table->timestamps();
        });

    }

    public function down()
    {
        Schema::dropIfExists('client_documents');
    }
}
Erik
  • 49
  • 7
  • 2
    Welcome to SO ... Models have a constructor already defined that actually does things, you just overrode that constructor to do nothing (how could a new instance be filled with attributes if you defined a constructor that doesn't take attributes and fill the model?) ... https://github.com/laravel/framework/blob/8.x/src/Illuminate/Database/Eloquent/Model.php#L204 – lagbox Nov 16 '21 at 17:58
  • 1
    You will need to at least call the parent constructor otherwise your constructor is empty and therefore useless – Aless55 Nov 16 '21 at 17:59
  • whether I add parent::__construct() or any other code in the __construct doesn't change anything, same error. I removed the code for simplicity... but maybe I shouldn't have! ;) I have edited my answer to make it clearer – Erik Nov 16 '21 at 18:03
  • 3
    It's more than just calling the parent constructor. The base [`Model`](https://github.com/laravel/framework/blob/8.x/src/Illuminate/Database/Eloquent/Model.php#L204) class has a constructor signature of `public function __construct(array $attributes = [])`, so you should make your constructor compatible with that signature and pass along the optional `$attributes` to the parent – Brian Thompson Nov 16 '21 at 18:06
  • Thank you Brian Thompson (and the others). I knew it was something like that, just couldn't find it. Thanks everyone. – Erik Nov 16 '21 at 18:09
  • Does this answer your question? [A \_\_construct on an Eloquent Laravel Model](https://stackoverflow.com/questions/30502922/a-construct-on-an-eloquent-laravel-model) – Don't Panic Nov 16 '21 at 21:08

1 Answers1

3

To close the question, I put the answer of Brian Thompson that was written in the comments:

"It's more than just calling the parent constructor. The base Model class has a constructor signature of public function __construct(array $attributes = []), so you should make your constructor compatible with that signature and pass along the optional $attributes to the parent"

So basically, I just changed my constructor code to:

public function __construct(array $attributes = []) {
    parent::__construct($attributes);
}   
Erik
  • 49
  • 7