Jac*_*cco 5 php mysql doctrine foreign-key-relationship doctrine-mapping
我们有一个数据库模式,以简化(略作作)的形式看起来像:
在列(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>
Run Code Online (Sandbox Code Playgroud)
但这给我一个错误:
UnitOfWork.php line 2649: Undefined index: groupId
所以,我的问题是:
在主义中描述多列多对一外键关系的正确方法是什么?
为了完整起见,数据库为上述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`);
Run Code Online (Sandbox Code Playgroud)
这对于你的问题来说并不是一个很好的答案。另外,我从未使用过 Doctrine 或 Doctrine2。但我花了一些时间环顾四周,最后几乎得到了前三个参考文献:
教义多重复合外键,一个问题,尽管它没有显示 XML 映射,并且可能是偏离基础的,至少它看起来是关于 FK 中的多列。并回答根据答案被忽略的 Doctrine2 的某些方面。
Doctrine2 映射具有复合外键的实体...这个问题没有收集太多价值,但至少可以作为一个欺骗候选者折叠到您的问题中。
XML 映射Doctrine2 XML 映射文档。它对文本搜索没有任何价值,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;
Run Code Online (Sandbox Code Playgroud)
一些临时工作:
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
Run Code Online (Sandbox Code Playgroud)
很明显,users并不真正需要复合 FK 到 中domains。相反,它只需要将单列 FK 放入 的替代 AI PK 中domains。这足以达到与您正在做的相同的效果。
与此一致,users.domainId就足够了,并且users.groupId引入了非规范化,后者应该被丢弃。
无论如何,希望这对您有所帮助。