推动单表继承问题
我有一个名为“talk”的表,它在我的 schema.xml 文件中定义为抽象。
它生成 4 个对象(每个类键 1 个):Comment、Rating、Review、Checkin
它还生成 TalkPeer,但我无法让它生成其他 4 个对等点(CommentPeer、RatingPeer、ReviewPeer、CheckinPeer),所以我通过以下方式创建了它们手,并让它们继承自TalkPeer.php,而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 应该只返回 Review 对象,而不能计算 知道如何做到这一点。
我真的必须检查并更改所有标准才能手动指定类键吗? 这似乎有点毫无意义,因为对等名称已经很明显了。 我不想定制每个 Peer。我应该能够自定义 TalkPeer,因为它们都继承自它......我只是不知道如何。
我尝试在 TalkPeer 中更改 doSelectStmt,以便它自动将 CLASSKEY 限制添加到 Criteria 中。它几乎可以工作,但我得到一个: Fatal error: Cannot instantiate Abstract class Talk in /models/om/BaseTalkPeer.php on line 503. Line 503 is in BaseTalkPeer::populateObjects(), is the 3rd line below:
$cls = TalkPeer::getOMClass($row, 0);
$cls = substr('.'.$cls, strrpos('.'.$cls, '.') + 1);
$obj = new $cls();
The < a href="http://propel.phpdb.org/trac/wiki/Users/Documentation/1.3/Inheritance" rel="nofollow noreferrer">文档讨论了重写 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。实在是太多了 需要重新测试的代码
I have a table called "talk", which is defined as abstract in my schema.xml file.
It generates 4 objects (1 per classkey): Comment, Rating, Review, Checkin
It also generates TalkPeer, but I couldn't get it to generate the other 4 peers (CommentPeer, RatingPeer, ReviewPeer, CheckinPeer), so I created them by hand, and made them inherit from TalkPeer.php, which inherits from BaseTalkPeer. I then implemented getOMClass() in each of those peers.
The problem is that when I do queries using the 4 peers, they return all 4 types of objects. That is, ReviewPeer will return Visits, Ratings, Comments, AND Reviews.
Example:
$c = new Criteria();
$c->add(RatingPeer::VALUE, 5, Criteria::GREATER_THAN);
$positive_ratings = RatingPeer::doSelect($c);
This returns all comments, ratings, reviews, & checkins that have a value > 5.
ReviewPeer should only return Review objects, and can't figure
out how to do this.
Do I actually have to go through and change all my criteria to manually specify the classkey?
That seems a little pointless, since the Peer name already distinct.
I don't want to have to customize each Peer. I should be able to customize JUST the TalkPeer, since they all inherit from it... I just can't figure out how.
I tried changing doSelectStmt just in TalkPeer so that it automatically adds the CLASSKEY restriction to the Criteria. It almost works, but I get a: Fatal error: Cannot instantiate abstract class Talk in /models/om/BaseTalkPeer.php on line 503. Line 503 is in BaseTalkPeer::populateObjects(), and is the 3rd line below:
$cls = TalkPeer::getOMClass($row, 0);
$cls = substr('.'.$cls, strrpos('.'.$cls, '.') + 1);
$obj = new $cls();
The docs talked about overriding BaseTalkPeer::populateObject(). I have a feeling that's my problem, but even after reading the source code, I still couldn't figure out how to get it to work.
Here is what I tried in 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);
}
Here is an example of my getOMClass method from ReviewPeer:
public static function getOMClass()
{
return self::CLASSNAME_4; //aka 'talk.Review';
}
Here is the relevant bit of my schema:
<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. - No, I can't upgrade from 1.3 to 1.4. There's just too much
code that would need to be re-tested
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为什么不删除abstract=true语句以便生成所有Peers,然后再次添加摘要,再次生成以获得完全符合您要求的数据库?
Why don't you just remove the abstract=true statements so you generate all Peers, then add the abstract again, generate again to get the db exactly as you like it?
我从未在 Propel 中使用过继承,但您应该能够修改每个 Peer 类上的 doSelectRS 方法来修改条件并指定继承键的额外条件。我面前没有文档,但在伪代码中它看起来像这样:
Ive never used inheritance in Propel but you should be able to modify the doSelectRS methods on each Peer class to modify the criteria and specify the extra condition for the inheritance key. I dont have the docs in front of me but in pseudo code itd look something like this: