Для 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) даже для таблиц, у которых нет первичного ключа .