Doctrine在SchemaCreateTable事件上添加列



我有一些ManyToMany表关系。

我想自动添加一个新列"created_at"。

根据Symfony和条令文件,我厌倦了这个:

app/config/services_dev.yaml

[...]
AppEventListenerManyToManyListener:
tags:
- { name: doctrine.event_listener, event: onSchemaCreateTable }

app/src/Event/Listener/ManyToManyListener.php


[.....]
class ManyToManyListener implements EventSubscriber
{
public function getSubscribedEvents()
{
return ['onSchemaCreateTable'];
}
public function onSchemaCreateTable(SchemaCreateTableEventArgs  $event)
{
$columns = $event->getTable()->getColumns();
if (count($columns) <= 2 && !array_key_exists("created_at", $columns)) {
$tableName = $event->getTable()->getName();
$sql = "ALTER TABLE $tableName ADD COLUMN created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP;";
$event->addSql($sql);
//dump($sql);
}
}
}

我可以把我的SQL代码转储到里面,它很有效。

我也尝试过这个代码(在if语句中(

$event->getTable()->addColumn(
"created_at",
"datetime",
["default" => "CURRENT_TIMESTAMP"]
);

这永远不会执行SQL语句。例如,当php bin/console doctrine:schema:update --dump-sql时,我看不到我的查询。

我浏览了条令代码,我明白不可能对这些事件执行我想要的操作,因为事件是在代码路径之后通过列调度的,例如在DoctrineDBALPlatformsAbstractPlatform

if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) {
$eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this);
$this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs);
if ($eventArgs->isDefaultPrevented()) {
return array_merge($eventArgs->getSql(), $columnSql);
}
}

因此,处理此事件的唯一方法是preventDefault并自己创建SQL。


通过查看代码,我找到了一个更好的方法:我修改了DoctrineORMToolsSchemaTool->getSchemaFromMetadata生成的模式

不确定这是最好的方法,但它非常有效。

AppEventSubscriberManyToManyListener:
tags:
- { name: doctrine.event_listener, event: postGenerateSchema }
class SchemaGeneratorListener
{
public function postGenerateSchema(GenerateSchemaEventArgs $event)
{
$tables = $event->getSchema()->getTables();
foreach ($tables as $table) {
$columns = $table->getColumns();
if (count($columns) <= 2 && !array_key_exists("created_at", $columns)) {
$event->getSchema()->getTable($table->getName())->addColumn(
"created_at",
'datetime',
["default" => "CURRENT_TIMESTAMP"]
);
}
}
}
}

最新更新