Проблема наследования единой таблицы Propel - PullRequest
2 голосов
/ 14 января 2010

У меня есть таблица «talk», которая определена как абстрактная в моем файле schema.xml.

Генерирует 4 объекта (по 1 на каждый ключ класса): комментарий, рейтинг, обзор, регистрация

Он также генерирует TalkPeer, но я не смог его сгенерировать для других 4 пиров (CommentPeer, RatingPeer, ReviewPeer, CheckinPeer), поэтому я создал их вручную и заставил наследовать их от TalkPeer.php, который наследуется от BaseTalkPeer. Затем я реализовал getOMClass () в каждом из этих пиров.

Проблема в в том, что когда я выполняю запросы с использованием четырех пиров, они возвращают все 4 типа объектов. То есть, ReviewPeer будет возвращать посещения, рейтинги, комментарии и отзывы.

Пример:

$c = new Criteria();
$c->add(RatingPeer::VALUE, 5, Criteria::GREATER_THAN);
$positive_ratings = RatingPeer::doSelect($c);

Возвращает все комментарии, рейтинги, отзывы и проверки, имеющие значение> 5.

ReviewPeer должен возвращать только объекты обзора и не может вычислить как это сделать.

Должен ли я на самом деле пройти и изменить все мои критерии, чтобы вручную указать ключ класса? Это кажется немного бессмысленным, так как имя Peer уже отличается. Я не хочу настраивать каждого пира. Я должен быть в состоянии настроить просто TalkPeer, так как все они наследуют от него ... Я просто не могу понять, как.

Я попытался изменить doSelectStmt только в TalkPeer, чтобы он автоматически добавлял ограничение CLASSKEY к Критериям. Это почти работает, но я получаю: Неустранимая ошибка: Невозможно создать экземпляр абстрактного класса Talk в /models/om/BaseTalkPeer.php в строке 503. Строка 503 находится в BaseTalkPeer :: populateObjects (), а третья строка ниже:

$cls = TalkPeer::getOMClass($row, 0); 
$cls = substr('.'.$cls, strrpos('.'.$cls, '.') + 1); 
$obj = new $cls();

В документах говорилось о переопределении 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);
    }

Вот пример моего метода getOMClass из ReviewPeer:

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 голосов
/ 22 января 2010

Почему бы вам просто не удалить оператор abstract = true, чтобы сгенерировать все одноранговые элементы, а затем снова добавить абстрактный, сгенерировать снова, чтобы получить db в точности так, как вам нравится?

0 голосов
/ 14 января 2010

Я никогда не использовал наследование в Propel, но вы должны иметь возможность изменять методы doSelectRS для каждого класса Peer, чтобы изменить критерии и указать дополнительное условие для ключа наследования. У меня нет документов передо мной, но в псевдокоде это выглядит примерно так:

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