我想CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
使用 Laravel Schema Builder/Migrations 的默认值创建一个时间戳列。我已经多次浏览 Laravel 文档,但我不知道如何将其设为时间戳列的默认值。
该timestamps()
函数为其创建0000-00-00 00:00
的两列都设置了默认值。
鉴于它是一个原始表达式,您应该使用DB::raw()
设置CURRENT_TIMESTAMP
为列的默认值:
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
这在每个数据库驱动程序上都能完美运行。
从 Laravel 5.1.25 开始(请参阅PR 10962和提交 15c487fe),您现在可以使用新的useCurrent()
列修饰符方法来为列实现相同的默认值:
$table->timestamp('created_at')->useCurrent();
回到问题,在 MySQL 上,您还可以ON UPDATE
通过以下方式使用子句DB::raw()
:
$table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
同样,从 Laravel 8.36.0(请参阅PR 36817)开始,您现在可以使用新的useCurrentOnUpdate()
列修饰符方法和useCurrent()
修饰符来为列实现相同的默认值:
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
MySQL
从 MySQL 5.7 开始,0000-00-00 00:00:00
不再被视为有效日期。正如Laravel 5.2 升级指南中所述,当您将记录插入数据库时,所有时间戳列都应该收到一个有效的默认值。您可以useCurrent()
在迁移中使用列修饰符(来自 Laravel 5.1.25 及更高版本)将时间戳列默认为当前时间戳,或者您可以使时间戳nullable()
允许空值。
PostgreSQL & Laravel 4.x
在 Laravel 4.x 版本中,PostgreSQL 驱动程序使用默认的数据库精度来存储时间戳值。当CURRENT_TIMESTAMP
在具有默认精度的列上使用该函数时,PostgreSQL 会生成具有更高可用精度的时间戳,从而生成带有小数秒部分的时间戳 -请参阅此 SQL fiddle。
这将导致 Carbon 无法解析时间戳,因为它不会期望存储微秒。为避免这种意外行为破坏您的应用程序,您必须明确地为CURRENT_TIMESTAMP
函数指定零精度,如下所示:
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP(0)'));
自 Laravel 5.0 起,timestamp()
列已更改为使用默认精度为零,从而避免了这种情况。
感谢@andrewhl在评论中指出 Laravel 4.x 问题。
感谢@ChanakaKarunarathne在评论中提出了新的useCurrentOnUpdate()
快捷方式。
要同时创建created_at
和updated_at
列:
$t->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$t->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
您将需要 MySQL 版本 >= 5.6.5 才能拥有多列CURRENT_TIMESTAMP
从 Laravel 5.1.26 开始,标记为 2015-12-02,useCurrent()
添加了一个修饰符:
Schema::table('users', function ($table) {
$table->timestamp('created')->useCurrent();
});
PR 10962(之后是提交 15c487fe)导致了这个添加。
基本上,MySQL 5.7(带有默认配置)要求您为时间字段定义默认值或可为空。
作为未来谷歌员工的额外可能性
我发现在创建记录但从未修改过时在 updated_at 列中有null更有用。它减少了数据库大小(好吧,只是一点点),并且可以第一眼看到数据从未被修改过。
至此,我使用:
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->default(DB::raw('NULL ON UPDATE CURRENT_TIMESTAMP'))->nullable();
(在带有 mysql 8 的 Laravel 7+8 中)。
编辑:从 Laravel 8 开始,您还可以使用:
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
归档相同的结果。
感谢@bilogic 指出这一点。
这对事实不起作用:
$table->timestamp('created_at')->default('CURRENT_TIMESTAMP');
它不会删除似乎与选择时间戳一起出现的“默认 0”,它只是附加了自定义默认值。但我们有点需要它没有引号。并非所有操作数据库的东西都来自 Laravel4。这就是他的观点。他希望在某些列上自定义默认值,例如:
$table->timestamps()->default('CURRENT_TIMESTAMP');
我认为 Laravel 不可能。我一直在寻找一个小时,看看是否有可能。
更新: Paulos Freita 的回答表明这是可能的,但语法并不简单。
请改用 Paulo Freitas的建议。
在 Laravel 修复此问题之前,您可以在运行后运行标准数据库查询Schema::create
。
Schema::create("users", function($table){
$table->increments('id');
$table->string('email', 255);
$table->string('given_name', 100);
$table->string('family_name', 100);
$table->timestamp('joined');
$table->enum('gender', ['male', 'female', 'unisex'])->default('unisex');
$table->string('timezone', 30)->default('UTC');
$table->text('about');
});
DB::statement("ALTER TABLE ".DB::getTablePrefix()."users CHANGE joined joined TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL");
它为我创造了奇迹。
在 laravel 7 中,要设置当前时间,请使用以下命令:
$table->timestamp('column_name')->useCurrent();
如果您要为 dateTime 列设置当前日期时间(就像我在谷歌上搜索时一样),请使用这种方式
$table->dateTime('signed_when')->useCurrent();
我在 Laravel 中使用以下自定义:
首先,我将helpers.php
在 Laravel 的根目录中创建一个文件 , 并插入以下内容:
<?php
if (!function_exists('database_driver')) {
function database_driver(): string
{
$connection = config('database.default');
return config('database.connections.' . $connection . '.driver');
}
}
if (!function_exists('is_database_driver')) {
function is_database_driver(string $driver): bool
{
return $driver === database_driver();
}
}
在 composer.json 中,我将以下内容插入到autoload
. 这允许作曲家自动发现 helpers.php。
"autoload": {
"files": [
"app/Services/Uploads/Processors/processor_functions.php",
"app/helpers.php"
]
},
我在我的 Laravel 模型中使用以下内容。
if (is_database_driver('sqlite')) {
$table->timestamps();
} else {
$table->timestamp('created_at')->default(\DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')
->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
}
这允许我的团队继续使用 sqlite 进行单元测试。ON UPDATE CURRENT_TIMESTAMP
是 MySQL 快捷方式,在 sqlite 中不可用。
这就是你的做法,我已经检查过了,它适用于我的 Laravel 4.2。
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
希望这可以帮助。
在 Laravel 5 中:
$table->timestamps(); //Adds created_at and updated_at columns.
文档: http: //laravel.com/docs/5.1/migrations#creating-columns