Doctrine 在SchemaCreateTable 事件上添加列

问题描述 投票:0回答:1

我有一些多对多表关系。

我想自动添加一个新列“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
时,我看不到我的查询。

php events doctrine symfony4
1个回答
1
投票

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

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"]
                );
            }
        }
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.