2010-01-14 90 views
2

我有一個名爲「talk」的表,它在我的schema.xml文件中定義爲abstract。Propel單表繼承問題

它產生4個對象(1元的ClassKey):評論,評分,評論,簽到

它也產生TalkPeer,但我無法得到它產生的其他4名同行(CommentPeer,RatingPeer,ReviewPeer, CheckinPeer),所以我手動創建了它們,並使它們繼承自TalkPeer.php,它繼承自BaseTalkPeer。然後我在每個對等體中實現了getOMClass()。

問題是,當我使用4個同位體進行查詢時,他們返回所有4種類型的對象。也就是說,ReviewPeer將返回訪問,評分,評論和評論。

例子:

$c = new Criteria(); 
$c->add(RatingPeer::VALUE, 5, Criteria::GREATER_THAN); 
$positive_ratings = RatingPeer::doSelect($c); 

這將返回所有評論,評分,評論,&簽有一個值> 5

ReviewPeer應該只返回評價對象,而不能圖 瞭解如何做到這一點。

我是否必須通過並更改所有條件才能手動指定classkey? 這似乎有點毫無意義,因爲Peer名稱已經不同。 我不想自定義每個對等。我應該可以自定義JUST TalkPeer,因爲它們都是從它繼承而來的......我只是無法弄清楚。

我試着在TalkPeer中更改doSelectStmt,以便它自動將CLASSKEY限制添加到Criteria。它幾乎可行,但我得到了一個:致命錯誤:無法在503行上實例化/models/om/BaseTalkPeer.php中的抽象類Talk。503行位於BaseTalkPeer :: populateObjects()中,並且是以下第3行:

$cls = TalkPeer::getOMClass($row, 0); 
$cls = substr('.'.$cls, strrpos('.'.$cls, '.') + 1); 
$obj = new $cls(); 

docs talked about overriding BaseTalkPeer::populateObject()我有一種感覺,那就是我的問題,但即使在閱讀源代碼之後,我仍然無法弄清楚如何使其工作。

以下是我在TalkPeer :: doSelectStmt嘗試:

public static function doSelectStmt(Criteria $criteria, PropelPDO $con = null) 
    { 
     $keys = array('models.Visit'=>1,'models.Comment'=>2,'models.Rating'=>3,'models.Review'=>4); 

     $class_name = self::getOMClass(); 

     if(isset($keys[$class_name])) 
     { //Talk itself is not a returnable type, so we must check 
      $class_key = $keys[$class_name]; 
      $criteria->add(TalkPeer::CLASS_KEY, $class_key); 
     } 

     return parent::doSelectStmt($criteria, $con = null); 
    } 

這裏是ReviewPeer我getOMClass方法的一個例子:

public static function getOMClass() 
{ 
    return self::CLASSNAME_4; //aka 'talk.Review'; 
} 

這裏是我的架構的相關位:

<table name="talk" idMethod="native" abstract="true"> 
    <column name="talk_pk" type="INTEGER" required="true" autoIncrement="true" primaryKey="true" /> 
    <column name="class_key" type="INTEGER" required="true" default="" inheritance="single"> 
     <inheritance key="1" class="Visit" extends="models.Talk" /> 
     <inheritance key="2" class="Comment" extends="models.Talk" /> 
     <inheritance key="3" class="Rating" extends="models.Talk" /> 
     <inheritance key="4" class="Review" extends="models.Rating" /> 
     </column> 
</table> 

PS - 不,我不能從1.3升級到1.4。有太多 代碼需要重新測試

回答

0

我從未在Propel中使用過繼承,但您應該能夠修改每個Peer類上的doSelectRS方法以修改條件並指定繼承的額外條件鍵。我沒有在文檔在我的面前,但是在僞代碼ITD是這個樣子:

public static function doSelectRS(Criteria $c) 
{ 
    // you may want to check if the condition already exists in one of the criterion's before doing the following... 
    $c->add(RatingPeer::TYPE, 3); 
    return parent::doSelectRS($c); 
} 
+0

沒有官方文檔提及這樣做,我想盡可能避免定製每個Peer。在處理Propel時,我認爲少量定製=更少的錯誤。 – 2010-01-14 21:18:47

+0

哈哈哦,我同意。以及文檔閱讀的方式,聽起來好像你正在做的一切正常。不明確的部分是你的問題的核心(雖然他們希望返回所有的子類,或者他們應該只返回所使用的對象的子類)。我不認爲它與重寫填充對象有任何關係 - 我認爲這就是如果你只想要適用於在實體中設置的給定子類的屬性。我沒有設置推動項目 - 你認爲你可以發佈「populateObjects」和「doSelect」的主體嗎? – prodigitalson 2010-01-14 21:32:12

+0

我認爲doSelectRS是一個Propel 1.2的東西。我記得它,但它並沒有在我的1.3代碼庫中找到:(我試着改變你的建議,但通過改變doSelectStmt。它幾乎可行,但我得到了一個:致命錯誤:無法在模型中實例化抽象類Talk第503行是在BaseTalkPeer :: populateObjects()中,並且是以下第3行: $ cls = TalkPeer :: getOMClass($ row,0); $ cls = substr(' 。'。$ cls,strrpos('。'。$ cls,'。')+ 1); $ obj = new $ cls(); – 2010-01-15 00:44:11

0

你爲什麼不只是刪除抽象= TRUE語句使你產生的所有同行,然後再添加抽象,再次生成獲取數據庫完全按照你喜歡的方式?

+0

無論我是否使用「抽象」,對等都不會自動生成。另外,DB *完全按我的喜好。 「抽象」部分就在那裏,因此Talk對象和對等點不會直接使用,因爲Talk必須是特定類型(Review/Rating/Visit/Comment)。 – 2010-01-22 20:19:38