我的迁移在本地工作,但在生产上失败,错误:

Migrating: 2024_03_19_145356_tasks

   Illuminate\Database\QueryException 

  SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'send_before' (SQL: create table `tasks` (`id` bigint unsigned not null auto_increment primary key, `subscription_id` bigint unsigned not null, `send_after` timestamp not null, `send_before` timestamp not null, `sent_at` timestamp null comment 'null = not sent', `failed_at` timestamp null, `delivered` tinyint(1) null default '0' comment '0 - not delivered, 1 - delivered, null - unknown', `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')

我的调试失败得很惨,因为SQL是有效的,事实上,当通过phpMyAdmin或终端运行时,它在生产环境中运行得很好:

create table `tasks` (`id` bigint unsigned not null auto_increment primary key, `subscription_id` bigint unsigned not null, `send_after` timestamp not null, `send_before` timestamp not null, `sent_at` timestamp null comment 'null = not sent', `failed_at` timestamp null, `delivered` tinyint(1) null default '0' comment '0 - not delivered, 1 - delivered, null - unknown', `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci'

2024_03_19_145356_tasks.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class Tasks extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->foreignId('subscription_id')->constrained('subscriptions')->cascadeOnDelete();
            $table->timestamp('send_after')->index();
            $table->timestamp('send_before')->index();
            $table->timestamp('sent_at')->nullable()->index()->comment('null = not sent');
            $table->timestamp('failed_at')->nullable();
            $table->boolean('delivered')->default(0)->comment('0 - not delivered, 1 - delivered, null - unknown')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

服务器版本:5.5.60-MariaDB MariaDB服务器

PHP 7.4.33(版本)(built:Dec 12 2023 14:45:16)(NTS)

Laravel框架8.83.27

UPDATED 1

dump(\DB::select("SELECT @@version, @@sql_mode"));添加到迁移中,我发现迁移过程中的sql_mode具有以下sql_mode设置:

array:1 [
  0 => {#1958
    +"@@version": "5.5.60-MariaDB"
    +"@@sql_mode": "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  }
]

UPDATED (SOLVED?)

我找到了问题所在.我不想假装我知道发生了什么,所以我会如实地说: 当迁移具有多于一个列类型timestampis not nullable时,问题就会出现.以下是一些例子:

作品:

Schema::create('tasks', function (Blueprint $table) {
    $table->id();
    $table->timestamp('test1');
    $table->timestamp('test2')->nullable();
    $table->timestamp('test3')->nullable();
});

错误1067 Invalid default value for 'test2':

Schema::create('tasks', function (Blueprint $table) {
    $table->id();
    $table->timestamp('test1');
    $table->timestamp('test2');
    $table->timestamp('test3')->nullable();
});

作品:

Schema::create('tasks', function (Blueprint $table) {
    $table->id();
    $table->timestamp('test1')->nullable();
    $table->timestamp('test2')->nullable();
    $table->timestamp('test3');
});

错误1067 Invalid default value for 'test2':

Schema::create('tasks', function (Blueprint $table) {
    $table->id();
    $table->timestamp('test1');
    $table->timestamp('test2');
});

作品:

Schema::create('tasks', function (Blueprint $table) {
    $table->id();
    $table->timestamp('test1')->nullable();
    $table->timestamp('test2');
    $table->timestamp('test3')->nullable();
});

而且...如果我用dateTime,它总是工作.所以...这个问题已经解决了,虽然我不知道发生了什么,我想知道,

推荐答案

timestamp列的隐式默认值(即,当您没有显式定义默认值时的默认值)是复杂的.它在表的第一个时间戳列之后的行为也不同.太奇怪了

如果您不指定任何默认值,第一个timestamp列会自动给出DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP个选项,并且explicit_defaults_for_timestamp为false.

后续的时间戳列不会自动获得这些选项.NOT NULL时间戳的隐式默认值是"default default"时间戳值,即0.

但是Laravel显然设置了一个包含NO_ZERO_IN_DATE,NO_ZERO_DATE的会话sql_mode,这使得timestamp的0值无效.

所以你的 Select 是:

  • 允许您的时间戳列为空.
  • 为该列显式地宣告DEFAULT.
  • 找出如何改变Laravel的最佳sql_mode个 idea ,允许零的日期.我不推荐这样做,因为带零的日期不是真正的日期.不允许他们是个好主意.

Php相关问答推荐

如何在Laravel Controller中存储文本区域值?

仅显示特定WooCommerce产品类别的额外产品字段

在WooCommerce中处理客户总支出中的退款

允许Laravel路由指定`withTrashed`,尽管有显式的模型绑定

从产品中获取WooCommerce产品属性单选按钮的列表WP_Query

自定义WooCommerce帐户下载列表

如何限制WordPress自定义分类术语页面中的术语数量

如何删除Foreach语句中的重复值?

在PHP中使用curl命令执行SCRAPYD操作.json不返回任何内容

如何在UML类图中可视化变量引用数组

创建一个Woocommerce我的帐户订单页面,仅显示已完成的订单

登录后重定向在WooCommerce中购买产品的用户

向WooCommerce管理订单总额添加自定义总额行

在PHP WordPress插件中使用变量连接路径时的问题解决方法

ACF 更新字段功能不更新 WordPress 中的任何数据

如果有很多重定向,PHP curl 的行为不像命令行 curl

从 CSV 文件 seeder 数据库时的额外行

将样式文件或脚本引入WordPress模板

在 DomPDF 和 Laravel 中使用内联 css

Laravel 响应 html 默认页面忽略控制器