Как описать внешний вид многоколоночного внешнего ключа в картографии Doctrine

У нас есть схема базы данных, которая в упрощенной (слегка надуманной) форме выглядит так:

введите описание изображения здесь

Если внешний ключ от пользователей до доменов установлен в столбцах (domainId, groupId), чтобы гарантировать ссылочную целостность. Эта структура отлично работает по назначению.

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

Я пробовал следующее:

<entity name="User" table="users"> <!-- other fields --> <many-to-one field="domain" target-entity="Domain" fetch="LAZY"> <join-columns> <join-column name="domainId" referenced-column-name="domainId"/> <join-column name="groupId" referenced-column-name="groupId"/> </join-columns> </many-to-one> </entity> 

Но это дает мне ошибку: UnitOfWork.php line 2649: Undefined index: groupId

Итак, мой вопрос:

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


Для полноты базы данных создайте код для схемы, как описано выше в ERD:

 CREATE TABLE `users` ( `userId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `groupId` INT(10) UNSIGNED NOT NULL, `domainId` INT(10) UNSIGNED NOT NULL, `someData` VARCHAR(32), PRIMARY KEY (`userId`), KEY `key_users_groupId_domainId` (`groupId`, `domainId`) ) ENGINE=InnoDB; CREATE TABLE `domains` ( `domainId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `groupId` INT(10) UNSIGNED NOT NULL, `someOtherData` VARCHAR(32), PRIMARY KEY (`domainId`), KEY `key_domains_groupId` (`groupId`) ) ENGINE=InnoDB; CREATE TABLE `groups` ( `groupId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `someMoreData` VARCHAR(32), PRIMARY KEY (`groupId`) ) ENGINE=InnoDB; ALTER TABLE `users` ADD CONSTRAINT `fk_users_domains` FOREIGN KEY (`groupId`, `domainId`) REFERENCES `domains` (`groupId`, `domainId`), ADD CONSTRAINT `fk_users_groups` FOREIGN KEY (`groupId`) REFERENCES `groups` (`groupId`); ALTER TABLE `domains` ADD CONSTRAINT `fk_domains_groups` FOREIGN KEY (`groupId`) REFERENCES `groups` (`groupId`); 

Это не фантастический ответ на ваш вопрос. Кроме того, я никогда не использовал Doctrine или Doctrine2. Но я провел некоторое время, оглядываясь по сторонам, и в значительной степени оказался в этих первых трех ссылках:

Doctrine множественный составной внешний ключ , вопрос, хотя он не отображает XML-сопоставления и может быть вне базы, по крайней мере, это похоже на несколько столбцов в FK. И ответьте на некоторые аспекты Doctrine2, которые игнорируются в соответствии с ответом.

Doctrine2 Создавайте объекты с составными внешними ключами в … Вопрос, который не получил большого значения, но может быть сложен в ваш вопрос как минимум.

XML-сопоставление Документация XML-документации Doctrine2. Это не имеет никакого значения при поиске в текстовом multi но поиск на composite говорит следующее:

Для составных клавиш вы можете указать более одного id-элемента, однако суррогатные ключи рекомендуются для использования с Doctrine 2.

Что привело меня к определению Википедии суррогата, в котором говорится:

Суррогат внутренне генерируется системой и невидим для пользователя или приложения.

И Природный против Суррогата . Обсуждение выбора между ними.

Вернемся к вашей модели, перечисленной в порядке убывания независимости:

 CREATE TABLE `groups` ( `groupId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `someMoreData` VARCHAR(32), PRIMARY KEY (`groupId`) ) ENGINE=InnoDB; CREATE TABLE `domains` ( `domainId` int(10) unsigned NOT NULL AUTO_INCREMENT, `groupId` int(10) unsigned NOT NULL, `someOtherData` varchar(32) DEFAULT NULL, PRIMARY KEY (`domainId`), KEY `key_domains_groupId` (`groupId`), CONSTRAINT `fk_domains_groups` FOREIGN KEY (`groupId`) REFERENCES `groups` (`groupId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `users` ( `userId` int(10) unsigned NOT NULL AUTO_INCREMENT, `groupId` int(10) unsigned NOT NULL, `domainId` int(10) unsigned NOT NULL, `someData` varchar(32) DEFAULT NULL, PRIMARY KEY (`userId`), KEY `key_users_groupId_domainId` (`groupId`,`domainId`), CONSTRAINT `fk_users_domains` FOREIGN KEY (`groupId`, `domainId`) REFERENCES `domains` (`groupId`, `domainId`), CONSTRAINT `fk_users_groups` FOREIGN KEY (`groupId`) REFERENCES `groups` (`groupId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Некоторые работы с царапинами:

 truncate table groups; -- disallowed delete from groups; alter table groups auto_increment 1; -- reset, after running delete from. insert groups(someMoreData) values ('group0001'),('group0002'); select * from groups; insert domains(groupId,someOtherData) values (1,'sod'),(1,'sod'),(1,'sod'), (2,'sod'),(2,'sod'); select * from domains; -- AI 1 to 5 above insert users(groupId,domainId,someData) values (1,1,'sd'); -- success insert users(groupId,domainId,someData) values (1,3,'sd'); -- success insert users(groupId,domainId,someData) values (1,4,'sd'); -- Error 1452 fk failure 

Совершенно очевидно, что users действительно не нужен составной FK для domains . Скорее, он просто нуждается в одном столбце FK в суррогатном AI PK domains . Это достаточно и достаточно плотно, чтобы добиться того же эффекта, что и вы.

В соответствии с этим, users.domainId достаточно, и users.groupId вводит денормализацию, а последний должен быть отброшен.

В любом случае, надеюсь, это поможет.