Laravel Voyager添加时间戳报错排查:MySQL设置问题
我之前也碰到过这个一模一样的问题,当时折腾了好一会儿才搞定,给你分享下我的解决思路和方案:
报错原因分析
这个错误的核心是MySQL的sql_mode配置限制了timestamp字段的默认值设置。从报错的SQL语句能看到:ALTER TABLE jobs ADD created_at timestamp null NOT NULL——这里同时写了null和NOT NULL本身就矛盾,再加上如果你的MySQL配置里的sql_mode包含NO_ZERO_IN_DATE、NO_ZERO_DATE或者STRICT_TRANS_TABLES这些严格校验选项,就会触发"Invalid default value"的报错。Voyager自动生成的SQL没有给timestamp字段设置合法的默认值,才导致了这个问题。
可行解决方案
方案1:修改MySQL的sql_mode配置(推荐)
这个方案能从根源解决问题,以后用Voyager创建带timestamps的表都不会再报错:
临时生效(重启MySQL后失效):
登录MySQL终端,执行以下命令:SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';执行完后退出MySQL重新登录,再尝试在Voyager里添加timestamps字段。
永久生效:
找到MySQL的配置文件(不同系统位置不同:Ubuntu/Debian一般是/etc/mysql/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf;Windows是MySQL安装目录下的my.ini),在[mysqld]节点下添加或修改:sql_mode = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"保存后重启MySQL服务即可。
方案2:手动执行合法的SQL添加字段
如果不想修改MySQL全局配置,可以绕过Voyager的自动生成逻辑,手动添加timestamps字段:
- 在Voyager创建表时,不要勾选timestamps选项,先完成表的创建。
- 登录MySQL终端,执行以下SQL来添加正确的timestamps字段:
这个语句给ALTER TABLE jobs ADD created_at timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, ADD updated_at timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL;created_at设置了默认当前时间,updated_at设置了默认当前时间且更新时自动刷新,完全符合MySQL的规则。
方案3:修改Voyager的字段生成逻辑(进阶)
如果需要长期让Voyager生成合法的timestamps字段定义,可以修改Voyager的源码:
- 找到Voyager处理表创建的逻辑文件(一般在
vendor/tcg/voyager/src/Http/Controllers/DatabaseController.php里的addTable方法),修改其中生成timestamps字段的代码,给字段加上DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP的定义。 - 注意:修改vendor包的代码会在更新Voyager时被覆盖,更稳妥的方式是创建Voyager的自定义扩展或者使用Laravel的服务提供者来重写相关逻辑。
注意事项
- 修改MySQL配置前,建议备份数据库,避免影响现有业务数据。
- 如果是给已有数据的表添加timestamps字段,手动执行SQL时要确保默认值不会破坏数据一致性。
内容的提问来源于stack exchange,提问作者brunam

