推动单表继承问题

时间:2010-01-14 20:32:32

标签: php orm propel single-table-inheritance

我有一个名为“talk”的表,在schema.xml文件中定义为abstract。

它生成4个对象(每个classkey 1个):Comment,Rating,Review,Checkin

它也会生成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);

这将返回所有评论,评分,评论和&签名的值> gt; 5。

ReviewPeer应该只返回Review对象,并且无法计算 如何做到这一点。

我是否真的必须通过并更改所有条件才能手动指定classkey? 这似乎有点无意义,因为同行的名字已经不同了。 我不想自定义每个Peer。我应该能够自定义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>

P.S。 - 不,我无法从1.3升级到1.4。太多了 需要重新测试的代码

2 个答案:

答案 0 :(得分:0)

我从未在Propel中使用继承,但您应该能够修改每个Peer类上的doSelectRS方法以修改条件并指定继承密钥的额外条件。我没有在我面前的文档,但在伪代码中它看起来像这样:

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);
}

答案 1 :(得分:0)

为什么不直接删除abstract = true语句,以便生成所有Peers,然后再次添加摘要,再次生成以完全按照您的喜好获取数据库?