2013-06-23 72 views
1

我正在使用Propel 1.7-dev,並且正在玩class delegation即表「繼承」。我已經將Propel1和Phing設置爲Git子模塊,並且每個都會在各自的主設備上檢出。我的模型可以構建,我可以使層次結構起作用,但是如果按照文檔(可以說更乾淨)來完成,那麼它就會失敗。如何使用Propel類代表團

這裏是我的模型的相關片段:

<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> 

有在實踐中更多的兒童模特,但我已經刪除它們的簡潔。

首先要注意的是,文檔顯示父類和子類的定義都是自動遞增的主鍵。但是,這是不可能的:主鍵必須在父級中設置,並複製到子級中(因爲父級將始終有一行)。我相信這是文檔中的一個錯誤,但是我會在這個問題後提供補丁,以防我誤解了某些內容。

所以,這是我的工作代碼:

$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)是問題所在 - 應該確定它在委託子上,並將該子項的主鍵更改爲提供的父項的鍵。顯然不是這樣做的。

,可能是相關的一些問題:

  • 有我理解正確的類委託?據我所知,父鍵應該是一個自動遞增的主鍵,並且這必須在孩子中用作手動主鍵來形成層次關係。 (另外:我原以爲會有一種方法可以自動確定父類型,但是由於它本身不會添加類型列,所以這是不可能的。這就是爲什麼我在父類中添加了enum手動)
  • 我可以使用Propel master而不是1.6.x正式版本打破某些東西嗎?

回答

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父:

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; 

這允許我使用級聯保存:

<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> 

這跨數據庫正確創建的約束根據文檔,耶! (a)我應該更仔細地閱讀文檔,(b)文檔說明許多:1完全正確的繼承,(c)與我的外鍵設置,1:1繼承也是可能的在推進。