我有一些多对多表关系。
我想自动添加一个新列“created_at”。
遵循 Symfony 和 Doctrine 文档,我厌倦了这个:
应用程序/config/services_dev.yaml
[...]
App\Event\Listener\ManyToManyListener:
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
时,我看不到我的查询。
我浏览了条令代码,我明白不可能对这些事件执行我想要的操作,因为事件是在通过列的代码路径之后调度的,例如在
Doctrine\DBAL\Platforms\AbstractPlatform
中
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。
查看代码,我发现了更好的方法: 我修改了
Doctrine\ORM\Tools\SchemaTool->getSchemaFromMetadata
生成的模式
不确定这是最好的方法,但它非常有效。
App\EventSubscriber\ManyToManyListener:
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"]
);
}
}
}
}