我正在使用Propel 1.7-dev并正在玩class delegation,即表"继承"。我已经将Propel1和Phing设置为Git子模块,并且每个都在各自的主人身上检查。我的模型构建,我可以让层次结构工作,但如果我按照文档(可以说更干净)来做,那么它就会失败。
这是我模特的相关片段:
<table name="process_step">
<column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
<column name="process_id" type="integer" required="true" />
<column name="ordinal" type="integer" required="true" />
<column name="comment" type="varchar" size="256" />
<column name="type" type="enum" required="true"
valueSet="load, submit_form, check_page, get_links"
/>
<column name="is_enabled" type="boolean" required="true" default="false" />
<foreign-key foreignTable="process">
<reference local="process_id" foreign="id" />
</foreign-key>
</table>
<table name="process_step_load">
<column name="id" type="integer" required="true" primaryKey="true" />
<behavior name="delegate">
<parameter name="to" value="process_step" />
</behavior>
<column name="url" type="varchar" size="1024" />
<column name="method" type="varchar" size="6" required="true" default="get" />
</table>
实际上还有更多的儿童模特,但我为了简洁而删除了它们。
首先要注意的是,docs显示父类和子类定义都具有自动递增的主键。但是,这是不可能的:必须在父级中设置主键,并将其复制到子级中(因为父级将始终有一行)。我认为这是文档中的一个错误,但是我会在这个问题之后提供补丁,以防我误解了某些内容。
所以,这是我的工作代码:
$process = new Process();
$processStep = new ProcessStep();
$processStep->setOrdinal(1); // Simplified for brevitiy
$processStep->setType(1); // Ditto
$processStep->setProcess($process);
// This creates a primary key which we use below (i.e. a cascading
// save won't work)
$processStep->save();
$processStepChild->setId($processStep->getId());
$processStepChild->save();
以下是文档如何拥有它:
$process = new Process();
$processStep = new ProcessStep();
$processStep->setOrdinal(1); // Simplified for brevitiy
$processStep->setType(1); // Ditto
$processStep->setProcess($process);
$processStepChild->setProcessStep($processStep);
$processStepChild->save();
这样做的结果是,在我创建四个子行(每个都是不同类型)的情况下,主键在父(ProcessStep)中设置正常但在子节点中都设置为零(ProcessStepLoad和其他)
即使我添加了中间保存,这也没有帮助。因此,在我看来$processStepChild->setProcessStep($processStep)
是问题 - 它应该在委托子项上,并将该子项的主键更改为提供的父项的键。显然没有这样做。
可能相关的一些问题:
答案 0 :(得分:1)
是的,我刚刚切换到MySQL的InnoDB引擎,所以我可以使用约束,我的新父表如下所示。这说明了出错的地方;表格上的关系是错误的:
CREATE TABLE `process_step`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`process_id` INTEGER NOT NULL,
`ordinal` INTEGER NOT NULL,
`comment` VARCHAR(256),
`type` TINYINT NOT NULL,
`is_enabled` TINYINT(1) DEFAULT 0 NOT NULL,
PRIMARY KEY (`id`),
INDEX `process_step_FI_1` (`process_id`),
CONSTRAINT `process_step_FK_1`
FOREIGN KEY (`process_id`)
REFERENCES `process` (`id`),
CONSTRAINT `process_step_FK_2`
FOREIGN KEY (`id`)
REFERENCES `process_step_load` (`id`)
ON DELETE CASCADE,
CONSTRAINT `process_step_FK_3`
FOREIGN KEY (`id`)
REFERENCES `process_step_submit_form` (`id`)
ON DELETE CASCADE,
CONSTRAINT `process_step_FK_4`
FOREIGN KEY (`id`)
REFERENCES `process_step_check_page` (`id`)
ON DELETE CASCADE,
CONSTRAINT `process_step_FK_5`
FOREIGN KEY (`id`)
REFERENCES `process_step_get_links` (`id`)
ON DELETE CASCADE
) ENGINE=InnoDB;
最后四个(对子表)当然是错误的:我们不能为每个孩子提供外键,因为这会要求每个孩子都要扩展每个孩子。事实证明,这种情况发生在孩子没有明确的FK的情况下。因此,我更改了模式中的类子项以将FK包含到父项:
<table name="process_step_load">
<column name="id" type="integer" required="true" primaryKey="true" />
<foreign-key foreignTable="process_step">
<reference local="id" foreign="id" />
</foreign-key>
<behavior name="delegate">
<parameter name="to" value="process_step" />
</behavior>
<column name="url" type="varchar" size="1024" />
<column name="method" type="varchar" size="6" required="true" default="get" />
</table>
这会在整个数据库中正确创建约束:
DROP TABLE IF EXISTS `process_step`;
CREATE TABLE `process_step`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`process_id` INTEGER NOT NULL,
`ordinal` INTEGER NOT NULL,
`comment` VARCHAR(256),
`type` TINYINT NOT NULL,
`is_enabled` TINYINT(1) DEFAULT 0 NOT NULL,
PRIMARY KEY (`id`),
INDEX `process_step_FI_1` (`process_id`),
CONSTRAINT `process_step_FK_1`
FOREIGN KEY (`process_id`)
REFERENCES `process` (`id`)
) ENGINE=InnoDB;
-- ---------------------------------------------------------------------
-- process_step_load
-- ---------------------------------------------------------------------
DROP TABLE IF EXISTS `process_step_load`;
CREATE TABLE `process_step_load`
(
`id` INTEGER NOT NULL,
`url` VARCHAR(1024),
`method` VARCHAR(6) DEFAULT 'get' NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `process_step_load_FK_1`
FOREIGN KEY (`id`)
REFERENCES `process_step` (`id`)
) ENGINE=InnoDB;
这允许我根据文档使用级联保存,耶!
故事的道德:(a)我应该更仔细地阅读文档,(b)文档说明很多:1完全正确的继承,(c)我的外键设置,1:1继承也是可能的推进。