我有一个名为“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。有太多 代码需要重新测试
没有官方文档提及这样做,我想尽可能避免定制每个Peer。在处理Propel时,我认为少量定制=更少的错误。 – 2010-01-14 21:18:47
哈哈哦,我同意。以及文档阅读的方式,听起来好像你正在做的一切正常。不明确的部分是你的问题的核心(虽然他们希望返回所有的子类,或者他们应该只返回所使用的对象的子类)。我不认为它与重写填充对象有任何关系 - 我认为这就是如果你只想要适用于在实体中设置的给定子类的属性。我没有设置推动项目 - 你认为你可以发布“populateObjects”和“doSelect”的主体吗? – prodigitalson 2010-01-14 21:32:12
我认为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