我在学说中有这种情况:发票及其相关的InvoiceItems。如果相关的Invoice已关闭,我可能会拒绝对InvoiceItems进行更改,可能是在Invoice的preSave方法中。我该怎么办?
答案 0 :(得分:2)
有几种可能性,你将如何实现这一点,它实际上取决于你的情况,应用程序业务逻辑等。(另外,你应该指定Doctrine分支,1.x或2.x)
它是完整性约束,在数据库级别执行:假设你的表上有一个preUpdate触发器,它会引发异常(只有一些DB可以做到这一点,想想Postgres,Oracle)或什么也不做,只是停止更新操作。
正如@jensgram建议的那样,你可以覆盖验证器方法,并返回无效状态,或者你可能抛出异常,因为这不是验证问题,因为它是完整性和逻辑约束,恕我直言
使用preSave方法,跳过保存(但用户不会发现任何事情)或再次,从中抛出异常。
在您的应用程序中,您不应该让用户完全陷入这种情况。您的GUI应该是明确的,并且清楚地显示发票已关闭且无法进一步修改。
就个人而言,我会使用这种情况: 首先,解决方案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);
}
这里有几点需要注意:
Company
(其中,state
必须“打开”)。最终结果取决于我是否找到满足这些标准的公司($company !== false
)isValid()
覆盖更深层次的实施。 始终使最终结果依赖于parent::isValid($deep, $hooks)
(我们必须确定原始实施也很满意。)