English 中文(简体)
Propel Single Table Inheritance Issue
原标题:

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

问题回答

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?

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:

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




相关问题
Brute-force/DoS prevention in PHP [closed]

I am trying to write a script to prevent brute-force login attempts in a website I m building. The logic goes something like this: User sends login information. Check if username and password is ...

please can anyone check this while loop and if condition

<?php $con=mysql_connect("localhost","mts","mts"); if(!con) { die( unable to connect . mysql_error()); } mysql_select_db("mts",$con); /* date_default_timezone_set ("Asia/Calcutta"); $date = ...

定值美元

如何确认来自正确来源的数字。

Generating a drop down list of timezones with PHP

Most sites need some way to show the dates on the site in the users preferred timezone. Below are two lists that I found and then one method using the built in PHP DateTime class in PHP 5. I need ...

Text as watermarking in PHP

I want to create text as a watermark for an image. the water mark should have the following properties front: Impact color: white opacity: 31% Font style: regular, bold Bevel and Emboss size: 30 ...

How does php cast boolean variables?

How does php cast boolean variables? I was trying to save a boolean value to an array: $result["Users"]["is_login"] = true; but when I use debug the is_login value is blank. and when I do ...

热门标签