Как в Doctrine игнорировать определенный столбец из команды обновления схемы?

У меня есть мой сопоставленный объект с именем Продукт, всего с двумя столбцами: id и name.

Если я добавлю еще один столбец вручную, то есть stock_qty непосредственно с оператором SQL, конечно же, с помощью инструмента обновления схемы удалю это.

Как я могу предотвратить удаление Doctrine моих настраиваемых столбцов, не сопоставленных с моей сущностью?

Связанные вопросы: https://github.com/doctrine/doctrine2/issues/6434

Напишите запрос на перенос, реализующий эту функцию

malarzm 24.11.2018 13:37
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
1
1 975
2

Ответы 2

Вы можете определить событие 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" в этом случае не будет удален)

Использованная литература:

События схемы доктрины

Слушатели событий Doctrine

Ответ Яннеса Ботиса был очень полезным. У меня были дополнительные проблемы с удалением индекса и внешнего ключа, хотя столбец игнорировался. Кроме того, в ходе миграции вниз продолжались попытки повторно добавить рассматриваемый столбец.

Далее следует мое расширенное решение, основанное на другом ответе.

<?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.

Другие вопросы по теме