Laravel 迁移默认值

Posted

技术标签:

【中文标题】Laravel 迁移默认值【英文标题】:Laravel migration default value 【发布时间】:2016-10-06 09:17:58 【问题描述】:

我不明白迁移中default 选项的作用是什么。

我可以看到数据库中的列是用默认值定义的,但是模型完全忽略了它。假设我有一个 Book 模型,它反映了数据库中的 books 表。我有迁移来创建 books 表:

Schema::create('books', function (Blueprint $table) 
    $table->increments('id');
          ->string('author');
          ->string('title');
          ->decimal('price', 4, 1)->default(100);
          ->timestamps();
);

当我创建 Book 模型的新实例时,我看到:

$book = new Book();
var_dump($book->price); //Always 0...

默认值被忽略,属性设置不正确。 好的,我可以得到它,因为它是一个新对象,它不应该从数据库中获取默认值。 但是如果我尝试保存模型,例如:

$book = new Book();
$book->author = 'Test'
$book->title = 'Test'
$book->save();

它是在数据库中的price字段中保存0

那么迁移中default 选项的意义何在?

顺便说一句... 如果模型在迁移中看到(如果存在)字段类型和行为是什么而不是在模型和迁移中手动定义它,那不是更好吗?此外,甚至可以为模型自动创建验证器。我认为迁移结构的微小变化是可能的,那为什么不是这样呢?

【问题讨论】:

在 Laravel 文档中,它说“在修改列之前,请务必将教义/dbal 依赖项添加到 composer.json 文件。Doctrine DBAL 库用于确定列的当前状态并创建对列进行指定调整所需的 SQL 查询。”你有这种依赖吗? 我没有修改任何列,我为什么要这样? 因为default($value) 是迁移中的修饰符,这是修饰符的先决条件。 【参考方案1】:

将默认值放在单引号中,它将按预期工作。迁移示例:

$table->increments('id');
            $table->string('name');
            $table->string('url');
            $table->string('country');
            $table->tinyInteger('status')->default('1');
            $table->timestamps();

编辑: 在你的情况下 ->default('100.0');

【讨论】:

它没有用。添加单引号并运行php artisan migrate:refresh 后仍然忽略默认值 我在发布答案之前对其进行了测试,您确定它不起作用吗?然后我会删除这个答案 用整数值试试?我知道您想要默认浮动,但请尝试一下 现在有了你的$table->tinyInteger('status')->default('1');,它就可以工作了。可能是因为我用来保存模型的Form::model。在那种情况下,我必须手动定义模型中的默认值吗? 它对我有用。但是有人知道这是否是预期的行为吗?看起来很奇怪。【参考方案2】:

您可以使用 default() 简单地设置默认值。看例子

 $table->enum('is_approved', array('0','1'))->default('0');

我这里使用了枚举,默认值为0。

【讨论】:

【参考方案3】:

在 Laravel 6 中,您必须将“更改”添加到迁移文件中,如下所示:

$table->enum('is_approved', array('0','1'))->default('0')->change();

【讨论】:

【参考方案4】:

参加聚会可能有点太晚了,但希望这对有类似问题的人有所帮助。

您的默认值不起作用的原因是迁移文件在您的数据库(mysql 或 PostgreSQL 等)中设置了默认值,而不是在您的 Laravel 应用程序中。

让我用一个例子来说明。

这行意味着 Laravel 正在生成一个新的 Book 实例,正如你的模型中指定的那样。新的Book 对象将根据与模型关联的表具有属性。到目前为止,数据库上没有写入任何内容。

$book = new Book();

现在以下几行设置Book 对象的每个属性的值。还是一样,数据库上还没有写任何东西。

$book->author = 'Test'
$book->title = 'Test'

这一行是写入数据库的行。将对象传递到数据库后,空字段将由数据库填充(可能是默认值,可能是 null,或者您在迁移文件中指定的任何值)。

$book->save();

因此,默认值在保存到数据库之前不会弹出。

但是,这还不够。如果您尝试访问$book->price,它仍然为空(或0,我不确定)。保存只是将默认值添加到数据库中的记录中,不会影响您随身携带的Object。

因此,要获取具有填充默认值的实例,您必须重新获取该实例。您可以使用

Book::find($book->id);

或者,通过刷新实例更复杂的方式

$book->refresh();

然后,下次您尝试访问该对象时,它将使用默认值填充。

【讨论】:

【参考方案5】:

您面临的问题与迁移文件无关。该值每次都变为 0,因为您没有更改模型上的 $fillable 。当您忘记将最近添加的列添加到其模型的 $fillable 时,Laravel 会插入 0。

【讨论】:

以上是关于Laravel 迁移默认值的主要内容,如果未能解决你的问题,请参考以下文章

在 laravel 迁移中使用 UUID 作为默认值

Laravel 迁移:添加具有现有列默认值的列

如果请求值为空,Laravel 设置默认值

Laravel Schema Builder 更新默认值

Laravel SQLite 字段的默认值

Laravel - 更改默认值 eloquent