Laravel 5.4中的字段没有默认值

39
我遇到了这个错误,但我在查找的所有谷歌结果中都没有找到类似于我的问题。
我的应用程序有一个名为Deal、User和Matches的类。
一个Deal有很多Matches。 一个User有很多Matches。 一个User有很多Deals。
我正在尝试使用我的Deal对象来创建一个新的Match。
$deal->matches()->create(['user_id'=>$id]);

这是我的匹配类,我已经定义了所有必要的关系

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');
    }
}

当我尝试创建一个新的比赛时,我一直遇到这个错误。

连接.php的QueryException在647行中出错: SQLSTATE [HY000]:一般错误:1364字段'user_id'没有默认值(SQL:insert into matches (deal_id) values (1))

我的guarded是一个空数组,可能有什么问题?


我不明白的是,如果它是一个中间表,为什么匹配需要一个模型类。https://laravel.com/docs/5.0/eloquent#working-with-pivot-tables - Indra
通常情况下,当您没有插入一个不可为空或没有默认值的特定字段时,就会生成此错误。因此,您的'user_id'未被插入。 - Cr1xus
@Cr1xus,是的,我的“user_id”没有被插入,现在我的问题是为什么会这样,因为我已经在我的创建方法中设置了它。 - John David
10个回答

101

移除guarded数组并添加fillable数组:

protected $fillable = ['user_id', 'deal_id'];

7
好的,我会翻译这段话。根据文档,使用 "guarded" 是没有问题的。 - John David
1
'guarded' 的作用与 'fillable' 相反(例如 $guarded = ['id'] 表示不允许更新 id),因此你应该使用 'fillable' 或 'guarded'。 - seb_dom

37
如果您想恢复以前的行为,请更新您的

config/database.php

文件,为您的连接设置 'strict' => false

你需要在此之后运行任何 artisan clear 命令或刷新迁移吗? - blamb
1
在 Laravel 5.5 中使用新命令 php artisan migrate:fresh --seed,尽情享受吧 :) - grantDEV
2
谢谢。所以,你的意思是它确实需要重新运行迁移吗?为了记录,我认为是 php artisan migrate:refresh --seed。除非有我不知道的新方法。;-) - blamb
2
是的,我做到了,它起作用了。migrate:fresh是一个新命令,请查看https://laravel-news.com/laravel-5-5。 - grantDEV

9

由于在我的情况下,这是一个独特的领域,所以我不能使它可为空。

对于我来说,我有一个空构造函数,这导致了问题,不知道为什么。 如果有人知道原因,请留言评论。

public function __construct(){

}

注释或删除它可以解决这个问题。


2
可以确认这是一个问题。我也遇到了这个问题。我删除了空构造函数类,"字段没有默认值"的错误就消失了。 - Derrick Miller
@vivek-takrani 请参考davee44的答案中的原因。显然,这些字段通过构造函数传递给父类。使用参数调用父类构造函数解决了我的问题。 - Vanlalhriata
2
确认。需要调用父构造函数并传递属性:https://dev59.com/31gQ5IYBdhLWcg3wLg05#59866152 - Alexander Ivashchenko
确认。类中的空构造函数是问题所在。 - puntable

9
如果你的模型中有构造函数,只需确保它也调用了父类构造函数:
public function __construct( array $attributes = array() ) {
    // mandatory
    parent::__construct($attributes);

    //..
}

否则,这将会破坏一些功能,例如 Model::create

这解决了我的问题。 - Hoytman
我花了很长时间来解决这个问题,但是直到我尝试了这个方法才得以解决。 - Urbycoz

7

我正在使用Laravel 8,并通过以下两个步骤解决了此错误:

  1. 将单词从User Model的$guarded数组移动到$fillable数组中

  2. 'mysql'数组中,将'strict' => false添加到Config.database.php中


5

解决此错误的另一种方法是在mysql数组中添加

'strict' => false,

在config/database.php文件中。


5

Alexey Mezenin的答案是正确和好的。

我采用的另一种方式,适用于那些想要维护受保护的空数组的人,就是创建一个新的Match对象,放入属性并保存。

            $match->user_id = $id;
            $match->deal_id = $deal->id;
            $match->matched_on = $match->freshTimestamp();
            $match->save();

1
当手动导入/导出数据库时,请检查所有表设置的传输是否成功。如果您忘记添加自增主键,则 Laravel 不会为您填充该值。
随后添加 AUTO_INCREMENT 将解决此问题。

0

我遇到了这个错误,但我的问题是创建类模型时出错了:

$book = new Book();

虽然这是真的

$book = new Book($request->all());

0

更改您的“config/database.php”是无济于事的。 如果您收到此错误消息,则说明您未正确将数据发送到数据库。 检查您控制器中的函数,create()方法可能被if语句或其他东西阻止了。 或者

如果这是一个API,请检查来自前端的post请求,这就是您的问题所在。 确保表单正确传递到请求中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接