доктрина опровергает обновления связанных записей из основной записи - PullRequest
1 голос
/ 24 марта 2011

У меня есть такая ситуация в доктрине: Счет-фактура с соответствующими элементами InvoiceItems.Я хотел бы отрицать изменения в InvoiceItems, если соответствующий Счет закрыт, возможно, в методе PreSave счета.Как мне это сделать?

Ответы [ 2 ]

2 голосов
/ 24 марта 2011

Есть несколько возможностей, как бы вы этого достигли, это действительно зависит от вашей ситуации, бизнес-логики приложения и т. Д. (Также вы должны указать ветвь Doctrine, 1.x или 2.x)

  1. Это ограничение целостности, делайте это на уровне базы данных: скажем, у вас есть триггер preUpdate для вашей таблицы, который либо вызовет исключение (это могут делать только некоторые БД, например Postgres, Oracle), либо ничего не сделает, просто остановите операция обновления.

  2. Как и предполагал @jensgram, вы можете переопределить метод validator и либо вернуть недопустимое состояние, либо вызвать исключение, потому что это не проблема проверки, так как это ограничение целостности и логики, IMHO

  3. Используйте метод preSave, либо пропустите сохранение (но пользователь ничего не заметит), либо снова выбросите из него исключение.

  4. В вашем приложении вы не должны позволять пользователю вообще попадать в эту ситуацию. Ваш графический интерфейс должен быть явным и четко отображать, что счет-фактура закрыт и не может быть изменен в дальнейшем.

Лично я бы использовал этот сценарий: Во-первых, решение № 4, не позволяйте пользователю делать это. Чтобы быть в безопасности, внедрите триггер непосредственно в базе данных, чтобы предотвратить ошибку в моем приложении в изменении закрытого счета, но делайте это молча, без ошибок, просто пропустите операцию сохранения (решение № 1). У этого подхода есть еще одно преимущество. Если вы окажетесь в ситуации, когда вам нужно будет подключиться к базе данных из любого другого приложения, это ограничение целостности будет сохранено.

0 голосов
/ 24 марта 2011

В Доктрина 1.x Я переопределил метод isValid() для бетона Doctrine_Record (здесь LineItem):

public function isValid($deep = false, $hooks = true) {
    $q = Doctrine_Query::create()
         ->select('co.uid')
         ->from('Company co')
         ->leftJoin('co.workers w')
         ->leftJoin('co.customers cust')
         ->leftJoin('cust.workCases wc')
         ->where('w.uid = ?', $this->_workerUid) // This LineItem's Worker must _always_ have the same Company as this LineItem (through LineItem -> WorkCase -> Customer -> Company)
         ->andWhere('wc.state = ?', WorkCase::STATE_OPEN) // This LineItem's WorkCase must be open
         ->andWhere('wc.uid = ?', $this->_caseUid);
    $company = $q->fetchOne();

    return $company !== false && parent::isValid($deep, $hooks);
}

Здесь следует отметить несколько вещей:

  1. Я пытаюсь получить Company на основе некоторых критериев (среди прочего, state должен быть "открытым").Конечный результат зависит от того, найду ли я компанию, которая удовлетворяет этим критериям ($company !== false)
  2. isValid(), переопределяет более глубокую реализацию. Всегда делает конечный результат зависимым от parent::isValid($deep, $hooks) (мы должны быть уверены, что оригинальная реализация также будет довольна).
  3. Вы, вероятно, могли бы упростить "выборку компании" в вашем случае.
...