Модели доктрин Symfony для сущности без первичных ключей - PullRequest
3 голосов
/ 08 декабря 2011

Я работаю с устаревшей базой данных, перестраивая веб-приложение. Я хочу использовать Symfony2.x, который, очевидно, имеет Doctrine в качестве ORM.

У меня около 50 (mysql) таблиц, в которых НЕТ первичных ключей. Когда я пытаюсь сгенерировать модели, он не дает мне сделать и выдает исключение с «No Primary Key on ... table».

Должен ли я иметь первичные ключи на столах, чтобы использовать Doctrine, или есть ли способ обойти это?

Любая помощь будет великолепна.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 02 апреля 2013

Для Doctrine требуется, чтобы имел идентификатор / первичный ключ .Взгляните на эту страницу: http://www.doctrine -project.org / docs / orm / 2.0 / en / reference / basic-mapping.html # идентификаторы-первичные ключи

Но есть - это способ создания сопоставлений и сущностей из таблиц, которые не имеют первичного ключа .Таблица без первичного ключа - это необычный и плохой дизайн базы данных, но такой сценарий существует в случае устаревших баз данных.

Решение : Примечание : Все ссылки ниже относятся к Доктрине 2.01. Найдите файл DatabaseDriver.php (в Doctrine / ORM / Mapping / Driver / DatabaseDriver.php)2. Найдите метод reverseEngineerMappingFromDatabase .Измените код, как указано ниже.Оригинальный код:

private function reverseEngineerMappingFromDatabase()
    {
        if ($this->tables !== null) {
            return;
        }

        $tables = array();

        foreach ($this->_sm->listTableNames() as $tableName) {
            $tables[$tableName] = $this->_sm->listTableDetails($tableName);
        }

        $this->tables = $this->manyToManyTables = $this->classToTableNames = array();
        foreach ($tables as $tableName => $table) {
            /* @var $table \Doctrine\DBAL\Schema\Table */
            if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
                $foreignKeys = $table->getForeignKeys();
            } else {
                $foreignKeys = array();
            }

            $allForeignKeyColumns = array();
            foreach ($foreignKeys as $foreignKey) {
                $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
            }

            if ( ! $table->hasPrimaryKey()) {
                throw new MappingException(
                    "Table " . $table->getName() . " has no primary key. Doctrine does not ".
                    "support reverse engineering from tables that don't have a primary key."
                );
            }

            $pkColumns = $table->getPrimaryKey()->getColumns();
            sort($pkColumns);
            sort($allForeignKeyColumns);

            if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) {
                $this->manyToManyTables[$tableName] = $table;
            } else {
                // lower-casing is necessary because of Oracle Uppercase Tablenames,
                // assumption is lower-case + underscore separated.
                $className = $this->getClassNameForTable($tableName);
                $this->tables[$tableName] = $table;
                $this->classToTableNames[$className] = $tableName;
            }
        }
    }

Модифицированный код:

private function reverseEngineerMappingFromDatabase()
    {
        if ($this->tables !== null) {
            return;
        }

        $tables = array();

        foreach ($this->_sm->listTableNames() as $tableName) {
            $tables[$tableName] = $this->_sm->listTableDetails($tableName);
        }

        $this->tables = $this->manyToManyTables = $this->classToTableNames = array();
        foreach ($tables as $tableName => $table) {
            /* @var $table \Doctrine\DBAL\Schema\Table */
            if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
                $foreignKeys = $table->getForeignKeys();
            } else {
                $foreignKeys = array();
            }

            $allForeignKeyColumns = array();
            foreach ($foreignKeys as $foreignKey) {
                $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
            }

            $pkColumns=array();
            if ($table->hasPrimaryKey()) {
                $pkColumns = $table->getPrimaryKey()->getColumns();
                sort($pkColumns);
            }

            sort($allForeignKeyColumns);

            if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) {
                $this->manyToManyTables[$tableName] = $table;
            } else {
                // lower-casing is necessary because of Oracle Uppercase Tablenames,
                // assumption is lower-case + underscore separated.
                $className = $this->getClassNameForTable($tableName);
                $this->tables[$tableName] = $table;
                $this->classToTableNames[$className] = $tableName;
            }
        }
    }

3. Найдите метод loadMetadataForClass в том же файле.Измените код, как указано ниже.Найдите код, указанный ниже:

try {
   $primaryKeyColumns = $this->tables[$tableName]->getPrimaryKey()->getColumns();
} catch(SchemaException $e) {
    $primaryKeyColumns = array();
}

Изменить это так:

try {
     $primaryKeyColumns = ($this->tables[$tableName]->hasPrimaryKey())?$this->tables[$tableName]->getPrimaryKey()->getColumns():array();
} catch(SchemaException $e) {
     $primaryKeyColumns = array();
}

Приведенное выше решение создает сопоставления (xml / yml / annotation) даже для таблиц, у которых нет первичного ключа .

1 голос
/ 08 декабря 2011

Доктрина требует, чтобы у каждого класса сущностей был идентификатор / первичный ключ.

Взгляните на эту страницу: http://www.doctrine -project.org / docs / orm / 2.0 / en / reference /базовый mapping.html # идентификаторы Второстепенного клавиш

0 голосов
/ 05 июня 2012

Такая ситуация возможна. например, я сопоставил представление с моделью, представление на самом деле не является таблицей. В этой ситуации мне нужна модель и мне не нужен первичный ключ

...