如何制作doctrine支持时间戳列?

时间:2016-01-13 18:43:39

标签: php doctrine-orm database-migration laravel-5.2 sql-timestamp

我尝试应用以下迁移:

Schema::table('users', function (Blueprint $table) {
    $table->timestamp('created_at')->useCurrent()->change();
});

artisan说:

  [Doctrine\DBAL\DBALException]
  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(). I
  f this error occurs during database introspection then you might have forgot to register all database types for a
  Doctrine Type. Use AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMapp
  edDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot some mapping inform
  ation.

当我尝试安装mmerian/doctrine-timestampcomposer install mmerian/doctrine-timestamp)时,composer说:

  [InvalidArgumentException]
  Could not find package mmerian/doctrine-timestamp at any version for your minimum-stability (stable). Check the pa
  ckage spelling or your minimum-stability

我该怎么办?

UPD 使用composer require mmerian/doctrine-timestamp=dev-master,我可以安装该软件包,然后在Type::addType('timestamp', 'DoctrineTimestamp\DBAL\Types\Timestamp');语句之前添加Schema::table,但现在我已经获得了其他错误:

  [Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'created_at' (SQL: ALTER TABLE u
  sers CHANGE created_at created_at INT DEFAULT 'CURRENT_TIMESTAMP' NOT NULL)

UPD 我再次检查它是否适用于mmerian/doctrine-timestamp,因为我当时只添加了文档中的第一行(或者文档已更新):

Type::addType('timestamp', 'DoctrineTimestamp\DBAL\Types\Timestamp');                                          
DB::getDoctrineConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('Timestamp', 'timestamp');

但它也没有帮助。迁移成功,但列定义没有变化。

4 个答案:

答案 0 :(得分:3)

嗨〜你可以使用“datetime”类型:

import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import {StoreModule, Store, Reducer, Action} from '@ngrx/store'

const CATEGORY = 'Snapshot';

export interface ISnapshotState {
      image?: any;
      element?: any;
    }


const initialState: ISnapshotState = {
};

interface ISNAPSHOT_ACTIONS {
  SNAPSHOT_NOW: string;
  SNAPSHOT_READY: string;
  SNAPSHOT_CLEAR: string;
}

export const SNAPSHOT_ACTIONS: ISNAPSHOT_ACTIONS = {
  SNAPSHOT_NOW: `[${CATEGORY}] SNAPSHOT_NOW`,
  SNAPSHOT_READY: `[${CATEGORY}] SNAPSHOT_READY`,
  SNAPSHOT_CLEAR: `[${CATEGORY}] SNAPSHOT_CLEAR`
};

export const snapshotReducer: ISnapshotState = (state: ISnapshotState = initialState, action: Action) => {


     switch(action.type){
        default:
          return state;
      }
    };

const rootReducer = {
  snapshot: snapshotReducer
}

@NgModule({
  declarations: [AppComponent],
  imports: [
    StoreModule.provideStore(rootReducer)
    ],
  providers: []
  ,
  bootstrap: [AppComponent]
})
export class AppModule { }

答案 1 :(得分:2)

可以看出,mmerian/doctrine-timestamp并未解决问题。首先,在this line $table->getColumns()['created_at']之后

class Doctrine\DBAL\Schema\Column#520 (16) {
  protected $_type => class Doctrine\DBAL\Types\DateTimeType#504 (0) { }
  protected $_length => NULL
  protected $_precision => int(10)
  protected $_scale => int(0)
  protected $_unsigned => bool(false)
  protected $_fixed => bool(false)
  protected $_notnull => bool(true)
  protected $_default => string(17) "CURRENT_TIMESTAMP"
  protected $_autoincrement => bool(false)
  protected $_platformOptions => array(0) { }
  protected $_columnDefinition => NULL
  protected $_comment => NULL
  protected $_customSchemaOptions => array(0) { }
  protected $_name => string(10) "created_at"
  protected $_namespace => NULL
  protected $_quoted => bool(false)
}

$this->getTableWithColumnChanges($blueprint, $table)->getColumns()['created_at']

class Doctrine\DBAL\Schema\Column#533 (16) {
  protected $_type => class DoctrineTimestamp\DBAL\Types\Timestamp#513 (0) { }
  protected $_length => NULL
  protected $_precision => int(10)
  protected $_scale => int(0)
  protected $_unsigned => bool(false)
  protected $_fixed => bool(false)
  protected $_notnull => bool(true)
  protected $_default => string(17) "CURRENT_TIMESTAMP"
  protected $_autoincrement => bool(false)
  protected $_platformOptions => array(0) { }
  protected $_columnDefinition => NULL
  protected $_comment => NULL
  protected $_customSchemaOptions => array(0) { }
  protected $_name => string(10) "created_at"
  protected $_namespace => NULL
  protected $_quoted => bool(false)
}

因此,首先我无法在此处查看有关ON UPDATE部分的信息。其次,onle差异是$_type值。我可以在this line之后确认,$tableDiff->changedColumns['created_at']->changedProperties

array(1) {
  [0] => string(4) "type"
}

然后,当generating ALTER TABLE statement时,一切都归结为此

public function getDefaultValueDeclarationSQL($field)
{
    $default = empty($field['notnull']) ? ' DEFAULT NULL' : '';
    if (isset($field['default'])) {
        $default = " DEFAULT '".$field['default']."'";
        if (isset($field['type'])) {
            if (in_array((string) $field['type'], array("Integer", "BigInt", "SmallInt"))) {
                $default = " DEFAULT ".$field['default'];
            } elseif (in_array((string) $field['type'], array('DateTime', 'DateTimeTz')) && $field['default'] == $this->getCurrentTimestampSQL()) {
                $default = " DEFAULT ".$this->getCurrentTimestampSQL();
            } elseif ((string) $field['type'] == 'Time' && $field['default'] == $this->getCurrentTimeSQL()) {
                $default = " DEFAULT ".$this->getCurrentTimeSQL();
            } elseif ((string) $field['type'] == 'Date' && $field['default'] == $this->getCurrentDateSQL()) {
                $default = " DEFAULT ".$this->getCurrentDateSQL();
            } elseif ((string) $field['type'] == 'Boolean') {
                $default = " DEFAULT '" . $this->convertBooleans($field['default']) . "'";
            }
        }
    }
    return $default;
}

this line附近,应该检查Timestamp类型以将'CURRENT_TIMESTAMP'变为CURRENT_TIMESTAMP。这可能在mmerian/doctrine-timestamp内吗?这个问题暂时搁置。这项检查很可能会解决我的特定问题。但是现在我要逃避这个:

DB::statement('ALTER TABLE users MODIFY COLUMN created_at
    TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');

答案 2 :(得分:0)

在composer.json中将minimum-stability设置为dev,因为mmerian/doctrine-timestamp只有dev-master版本,例如:

{
    "minimum-stability": "dev",
    "require": {
        ...
     }
}

Then, when bootstraping your doctrine connection

Type::addType('timestamp', 'DoctrineTimestamp\DBAL\Types\Timestamp');
$conn->getDatabasePlatform()->registerDoctrineTypeMapping('Timestamp', 'timestamp');

答案 3 :(得分:0)

我为它构建了this,因为Doctrine不想支持它,因为它是特定于MySQL的列类型。