39

I am having this error and none of the googled result i checked is similar to my problem.

I have an application with class Deal, User, and Matches

A deal has many matches. A user has many matches. A user has many deals.

I am attempting to create a new Match using my Deal object

$deal->matches()->create(['user_id'=>$id]);

This is my match class, i have defined all needed relationships

class Match extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $guarded = [];
    public $timestamps = false;
    public $expired_on = "";


    public static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            $model->matched_on = $model->freshTimestamp();
        });
    }

    public function __construct(){
        $d = (new \DateTime($this->matched_on))->modify('+1 day');
        $this->expired_on = $d->format('Y-m-d H:i:s');
    }


    /**
     * Get the user that owns the match.
     */
    public function user()
    {
        return $this->belongsTo('App\User');
    }

    /**
     * Get the deal that owns the match.
     */
    public function deal()
    {
        return $this->belongsTo('App\Deal');
    }
}

And i keep getting this error when i attempt to create a new match.

QueryException in Connection.php line 647: SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into matches (deal_id) values (1))

I have my guarded to be an empty array, what could be the problem?

Ari
  • 745
  • 1
  • 7
  • 23
John David
  • 752
  • 2
  • 9
  • 21
  • What I don't get is why matches has a model class if it's a pivot table https://laravel.com/docs/5.0/eloquent#working-with-pivot-tables – Indra Apr 03 '17 at 13:58
  • This is usually generated when you don't insert a certain field that cannot be NULL or doesn't have a default value. So your 'user_id' does not get inserted – Cr1xus Apr 03 '17 at 14:05
  • @Cr1xus, yes my 'user_id' does not get inserted, my issue now is why is it so, seeing that i have it in my create method. – John David Apr 03 '17 at 15:03

10 Answers10

101

Remove the guarded array and add the fillable instead:

protected $fillable = ['user_id', 'deal_id'];
Alexey Mezenin
  • 158,981
  • 26
  • 290
  • 279
  • 7
    Will do that, but nothing is wrong with using _guarded_ according to the documentation – John David Apr 03 '17 at 14:59
  • 1
    'guarded' does the opposite (like $guarded = ['id']; means do not allow to update the id), so, you should either use 'fillable' or 'guarded'. – seb_dom Jan 18 '22 at 21:27
37

If you would like to revert to previous behavior, update your

config/database.php

file and set 'strict' => false for your connection.

grantDEV
  • 552
  • 1
  • 6
  • 10
  • Do you need to run any artisan clear commands, or refresh migrate after this? – blamb Sep 20 '17 at 17:32
  • 1
    Use new comand in Laravel 5.5 php artisan migrate:fresh --seed and have fun :) – grantDEV Sep 21 '17 at 10:33
  • 2
    Thanks. So, your saying it does need a rerun of the migration then? For the record i think that is `php artisan migrate:refresh --seed`. Unless there is a fresh I don't know about. ;-) – blamb Sep 21 '17 at 18:56
  • 2
    yes I did that and it worked, migrate:fresh is new command look that https://laravel-news.com/laravel-5-5 – grantDEV Sep 21 '17 at 22:15
9

Since it was a unique field in my case, I could not make it nullable.

For me, I had an empty constructor which was causing the issue don't know why. Please comment if anyone knows the reason.

public function __construct(){

}

Commenting/removing it resolved the issue.

vivek takrani
  • 3,858
  • 2
  • 19
  • 33
  • 2
    Can confirm this is a thing. I just ran into it as well. I removed the empty constructor class and the "field doesn't have a default value" error disappeared. – Derrick Miller May 02 '19 at 19:01
  • @vivek-takrani See [davee44's answer](https://stackoverflow.com/a/59866152/2530736) for the reason. Apparently the fields get passed to the parent through the constructor. Calling the parent constructor with arguments solved the problem for me. – Vanlalhriata May 29 '20 at 15:55
  • 2
    Confirmed. Need to call parent constructor ! and pass attributes: https://stackoverflow.com/a/59866152/3163536 – Alexander Ivashchenko Jul 18 '20 at 08:58
  • Confirmed. Empty constructor in class was the problem. – puntable Aug 26 '20 at 15:43
9

If you have a constructor in your model, just make sure it has a call to a parent constructor as well:

public function __construct( array $attributes = array() ) {
    // mandatory
    parent::__construct($attributes);

    //..
}

Otherwise, it will break some functionality like Model::create.

davee44
  • 357
  • 3
  • 10
7

I am using Laravel 8 and fixed this error thorugh this two steps:

  1. move the word from $guarded array to $fillable array in User Mode

  2. Config.database.php: 'strict' => false in the array of 'mysql'

W Kenny
  • 1,855
  • 22
  • 33
5

Alexey Mezenin's Answer is correct and a good one.

Another way i used around it, for those who want to maintain the guarded empty array is to create a new Match object and put in the attributes and save.

            $match->user_id = $id;
            $match->deal_id = $deal->id;
            $match->matched_on = $match->freshTimestamp();
            $match->save();
John David
  • 752
  • 2
  • 9
  • 21
5

Another way around this error is to include

'strict' => false,

into config/database.php within mysql array

1

When manually importing / exporting the databases, check if the transfer of all table settings was successful. If you forget to add an auto increment primary key, Laravel doesn't fill the value for you.

Adding the AUTO_INCREMENT afterwards will solve the problem.

mhellmeier
  • 1,982
  • 1
  • 22
  • 35
0

I had this error but my wrong was making class model:

$book = new Book();

While this is true

$book = new Book($request->all());
ParisaN
  • 1,816
  • 2
  • 23
  • 55
0

changing your "config/database.php" won't help. If you're getting this error, you're not sending the data to database correctly. check your function in your controller, the create() method is probably being blocked by an if statement or something. or

if it's an API, check the post request from the frontend that's where your issue is. make sure the form is correctly passed into to request.