学说拒绝主记录中相关记录的更新

时间:2011-03-24 10:14:04

标签: php doctrine

我在学说中有这种情况:发票及其相关的InvoiceItems。如果相关的Invoice已关闭,我可能会拒绝对InvoiceItems进行更改,可能是在Invoice的preSave方法中。我该怎么办?

2 个答案:

答案 0 :(得分:2)

有几种可能性,你将如何实现这一点,它实际上取决于你的情况,应用程序业务逻辑等。(另外,你应该指定Doctrine分支,1.x或2.x)

  1. 它是完整性约束,在数据库级别执行:假设你的表上有一个preUpdate触发器,它会引发异常(只有一些DB可以做到这一点,想想Postgres,Oracle)或什么也不做,只是停止更新操作。

  2. 正如@jensgram建议的那样,你可以覆盖验证器方法,并返回无效状态,或者你可能抛出异常,因为这不是验证问题,因为它是完整性和逻辑约束,恕我直言

  3. 使用preSave方法,跳过保存(但用户不会发现任何事情)或再次,从中抛出异常。

  4. 在您的应用程序中,您不应该让用户完全陷入这种情况。您的GUI应该是明确的,并且清楚地显示发票已关闭且无法进一步修改。

  5. 就个人而言,我会使用这种情况: 首先,解决方案4,不允许用户这样做。为了安全起见,直接在数据库中实现触发器,以防止我的应用程序中的错误更改已关闭的发票,但是无声地执行,没有引发错误,只是跳过保存操作(解决方案1)。这种方法还有一个优点。如果您遇到这种情况,当您需要从任何其他应用程序连接到数据库时,将保留该完整性约束。

答案 1 :(得分:0)

Doctrine 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. 你可以在你的情况下简化“获取公司记录”。