У меня есть мой сопоставленный объект с именем Продукт, всего с двумя столбцами: id и name.
Если я добавлю еще один столбец вручную, то есть stock_qty непосредственно с оператором SQL, конечно же, с помощью инструмента обновления схемы удалю это.
Как я могу предотвратить удаление Doctrine моих настраиваемых столбцов, не сопоставленных с моей сущностью?
Связанные вопросы: https://github.com/doctrine/doctrine2/issues/6434






Вы можете определить событие onSchemaColumnDefinition или onSchemaAlterTableRemoveColumn и игнорировать эти столбцы.
Использование события onSchemaAlterTableRemoveColumn
В вашем пакете создайте, например. src / AppBundle / EventListener / MyEventListener.php:
namespace AppBundle\EventListener;
use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
use Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs;
class MyEventListener
{
public function onSchemaAlterTableRemoveColumn(SchemaAlterTableRemoveColumnEventArgs $args)
{
$tableColumn = $args->getColumn();
$table = $args->getTableDiff();
if ($table->name == 'tableName' && $tableColumn->getName() == 'columnName') {
$args->preventDefault();
}
}
}
Затем зарегистрируйте прослушиватель событий в своих сервисах:
services:
AppBundle\EventListener\MyEventListener:
tags:
- { name: doctrine.event_listener, event: onSchemaAlterTableRemoveColumn }
Похоже, вы могли бы сделать это:
Использование события onSchemaColumnDefinition
В вашем пакете создайте, например. src / AppBundle / EventListener / MyEventListener.php:
namespace AppBundle\EventListener;
use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
use Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs;
class MyEventListener
{
public function onSchemaColumnDefinition(SchemaColumnDefinitionEventArgs $args)
{
$tableColumn = $args->getTableColumn();
$table = $args->getTable();
if ($table == 'tableName' && $tableColumn['Field'] == 'columnName') {
$args->preventDefault();
}
}
}
Затем зарегистрируйте прослушиватель событий в своем services.yml:
services:
AppBundle\EventListener\MyEventListener:
tags:
- { name: doctrine.event_listener, event: onSchemaColumnDefinition }
При беге:
php bin/console doctrine:schema:update --force
должен игнорировать указанные столбцы. ("tableName". "columnName" в этом случае не будет удален)
Использованная литература:
Ответ Яннеса Ботиса был очень полезным. У меня были дополнительные проблемы с удалением индекса и внешнего ключа, хотя столбец игнорировался. Кроме того, в ходе миграции вниз продолжались попытки повторно добавить рассматриваемый столбец.
Далее следует мое расширенное решение, основанное на другом ответе.
<?php
namespace App\Listener\Doctrine;
use Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs;
use Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs;
class DoctrineListener
{
protected $ignoreFields;
public function __construct($doctrineIgnoreFields)
{
$this->ignoreFields = $doctrineIgnoreFields;
}
public function onSchemaAlterTableAddColumn(SchemaAlterTableAddColumnEventArgs $args)
{
$tableDiff = $args->getTableDiff();
if (in_array($tableDiff->name, array_keys($this->ignoreFields))) {
$tableName = $tableDiff->name;
$tableColumn = $args->getColumn();
if (in_array($tableColumn->getName(), $this->ignoreFields[$tableName])) {
$columnName = $tableColumn->getName();
if ($tableColumn->getName() == $columnName) {
$tableDiff = $args->getTableDiff();
unset($tableDiff->addedColumns[$columnName]);
foreach ($args->getTableDiff()->addedIndexes as $index => $addedIndex) {
foreach ($addedIndex->getColumns() as $column) {
if ($column === $columnName) {
unset($tableDiff->addedIndexes[$index]);
$args->preventDefault();
}
}
}
foreach ($args->getTableDiff()->addedForeignKeys as $index => $foreignKey) {
foreach ($foreignKey->getColumns() as $column) {
if ($column === $columnName) {
unset($tableDiff->addedForeignKeys[$index]);
$args->preventDefault();
}
}
}
}
}
}
}
public function onSchemaAlterTableRemoveColumn(SchemaAlterTableRemoveColumnEventArgs $args)
{
$tableDiff = $args->getTableDiff();
if (in_array($tableDiff->name, array_keys($this->ignoreFields))) {
$tableName = $tableDiff->name;
$tableColumn = $args->getColumn();
if (in_array($tableColumn->getName(), $this->ignoreFields[$tableName])) {
$columnName = $tableColumn->getName();
$args->preventDefault();
unset($tableDiff->removedColumns[$columnName]);
foreach ($args->getTableDiff()->removedIndexes as $index => $removedIndex) {
foreach ($removedIndex->getColumns() as $column) {
if ($column === $columnName) {
unset($tableDiff->removedIndexes[$index]);
$args->preventDefault();
}
}
}
foreach ($args->getTableDiff()->removedForeignKeys as $index => $removedForeignKey) {
foreach ($removedForeignKey->getColumns() as $column) {
if ($column === $columnName) {
unset($tableDiff->removedForeignKeys[$index]);
$args->preventDefault();
}
}
}
}
}
}
}
Конфигурация:
services:
# default configuration for services in *this* file
_defaults:
...
bind:
$doctrineIgnoreFields:
'table_a':
- 'column_a'
- 'column_b'
'table_b':
- 'column_c'
- 'column_d'
App\Listener\Doctrine\DoctrineListener:
tags:
- { name: doctrine.event_listener, event: onSchemaAlterTableAddColumn }
- { name: doctrine.event_listener, event: onSchemaAlterTableRemoveColumn }
Это решение было протестировано на Symfony 4.4.
Напишите запрос на перенос, реализующий эту функцию