Метод onAfterWrite вызывается дважды с DataObjectManager

Я использую dataobjectmanager с отношением many_many (я не могу использовать для этого manymanydataobjectmanager) между владельцем и автомобилем. Всякий раз, когда создается новый автомобиль, я перебираю все экземпляры владельца и добавляю его идентификатор в связанную таблицу вместе с идентификатором нового автомобиля.

Моя проблема в том, что код для этого находится в методе onafterwrite и вызывается дважды. Я не уверен, почему. Я также заметил, что для трех моих владельцев он странно создает строки в связанной таблице. Первые два идентификатора будут в порядке, затем он будет придерживаться одного. Таким образом, это будут ряды 1, 2 и 4 без 3.

Это мой метод onAfterWrite

public function onAfterWrite() {

    if(Permission::check('ADMIN')){
        $Pages = DataObject::get('Owner');              

        foreach($Pages as $owner) {

        DB::query("INSERT INTO Owner_Cars (OwnerID, CarID) VALUES ('". $owner->ID . "', '" . $this->ID . "')");
        }
    }
    else {
        echo "Failure";
        return false;
    }
    return parent::onAfterWrite();
}

Я был бы признателен за любой совет, который вы могли бы мне дать.

Спасибо


person MillyMonster    schedule 24.08.2012    source источник
comment
Не можете использовать менеджер объектов manymanydata? Это техническое ограничение, или вы просто предпочитаете его не использовать? Я никогда не заставлял dataobjectmanager работать с отношением «многие ко многим» в SilverStripe.   -  person Benjamin Smith    schedule 25.08.2012
comment
думаю, это то же самое, что и с «onBeforeWrite», см. эту ветку для объяснения и обходного пути: silverstripe.org/data-model-questions/show/6805   -  person schellmax    schedule 25.08.2012


Ответы (1)


Вероятно, метод onAfterWrite() вызывается дважды, потому что write() вызывается дважды. Наиболее распространенная причина, по которой это происходит, заключается в том, что:

  • Write() генерирует идентификатор
  • Затем происходит еще одна запись () как часть сохранения связанных записей, которые зависят от этого идентификатора.

В общем, я не думаю, что вы можете полагаться на то, что onAfterWrite() вызывается один раз: предполагается, что функция write() спроектирована таким образом, чтобы ее можно было вызывать сколько угодно раз, и она фактически повлияет на базу данных только в том случае, если в нее будут внесены изменения. быть сделано.

Вам нужно будет сделать так, чтобы ваш код вызывал необходимые операторы DELETE, INSERT и/или UPDATE, чтобы быть совместимым с этим. Например, вы можете:

  • Выберите все записи Owner_Cars, где OwnerID = $owner->ID
  • Удалите все, чего нет в списке $Pages
  • Вставьте любой из списка $Page, которого еще нет в Owner_Cars

Еще одно предложение, которое я хотел бы сделать, если вы можете, — попробовать SilverStripe 3. GridField SilverStripe 3 более надежно справляется с такими вещами из коробки, и вам может быть проще построить свое приложение на этом.

person Sam Minnée    schedule 14.10.2012
comment
Спасибо за ответ Сэм. С тех пор я узнал в значительной степени то, что вы сказали, но спасибо за ответ. Это прояснило мои оставшиеся вопросы. - person MillyMonster; 15.10.2012