Laravel6迁移修改timestamp字段报未知列类型错误如何解决
Laravel 6 修改字段为timestamp类型报错解决方案
问题场景
初始开发时创建work_schedule_times表,将start_time、end_time字段设置为time类型,初始迁移代码:
Schema::create('work_schedule_times', function (Blueprint $table) { $table->time('start_time'); $table->time('end_time'); });
后续需要编写新迁移,将employee_work_schedules表的对应字段从time类型修改为timestamp类型,最初编写的修改迁移代码:
Schema::table('employee_work_schedules', function (Blueprint $table) { $table->timestamp('start_time')->change(); $table->timestamp('end_time')->nullable()->change(); });
执行迁移命令时抛出如下错误:
Unknown column type "timestamp" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database introspection then you might have forgotten to register all database types for a Doctrine Type. Use AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot some mapping information.
Laravel 9 官方提供的修复方案是在config/database.php中添加DBAL配置注册timestamp类型,但该方案依赖Laravel 9内置的Illuminate\Database\DBAL\TimestampType类,Laravel 6 无该类,无法直接使用。
适配Laravel 6的可行方案
前置检查
使用->change()方法修改字段前,必须先安装兼容版本的doctrine/dbal依赖,Laravel 6 最高兼容2.x版本,执行安装命令:
composer require doctrine/dbal:^2.0
禁止安装3.x及以上版本的dbal,会出现框架版本兼容问题
方案1:迁移内手动注册DBAL类型映射(推荐)
报错核心原因是Laravel 6 依赖的doctrine/dbal 2.x版本没有内置timestamp的类型映射,直接在迁移文件的方法开头手动注册映射即可,不需要修改全局配置。
完整迁移代码示例:
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\DateTimeType; class ModifyEmployeeWorkSchedulesTimeFields extends Migration { public function up() { // 注册timestamp类型映射 if (!Type::hasType('timestamp')) { Type::addType('timestamp', DateTimeType::class); } DB::getDoctrineConnection() ->getDatabasePlatform() ->registerDoctrineTypeMapping('timestamp', 'datetime'); Schema::table('employee_work_schedules', function (Blueprint $table) { $table->timestamp('start_time')->change(); $table->timestamp('end_time')->nullable()->change(); }); } public function down() { // 回滚时也需要注册映射,否则回滚会报同样错误 if (!Type::hasType('timestamp')) { Type::addType('timestamp', DateTimeType::class); } DB::getDoctrineConnection() ->getDatabasePlatform() ->registerDoctrineTypeMapping('timestamp', 'datetime'); Schema::table('employee_work_schedules', function (Blueprint $table) { $table->time('start_time')->change(); $table->time('end_time')->nullable()->change(); }); } }
方案2:执行原生SQL修改字段(无依赖问题)
如果不想处理DBAL类型映射逻辑,可以直接执行原生SQL语句完成字段修改,完全绕过->change()方法的依赖限制。
注意:原生SQL需要和当前使用的数据库类型匹配,以下示例为MySQL语法,使用其他数据库请自行调整字段修改语法,同时要和原有字段的非空、默认值属性保持一致,避免丢失字段配置。
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Support\Facades\DB; class ModifyEmployeeWorkSchedulesTimeFields extends Migration { public function up() { DB::statement(" ALTER TABLE employee_work_schedules MODIFY COLUMN start_time TIMESTAMP NOT NULL, MODIFY COLUMN end_time TIMESTAMP NULL "); } public function down() { DB::statement(" ALTER TABLE employee_work_schedules MODIFY COLUMN start_time TIME NOT NULL, MODIFY COLUMN end_time TIME NULL "); } }
内容的提问来源于stack exchange,提问作者hassan
相关产品推荐
相关产品推荐

