2010-01-14 93 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