我正在PHP+Zend Framework上实现一个非常简单的会计程序。我设置了这个触发器:
CREATE TRIGGER consolidate_balance BEFORE INSERT ON balance FOR EACH ROW
BEGIN
IF (NEW.amount IS NOT NULL) THEN
UPDATE accounts SET accounts.balance = accounts.balance + NEW.amount WHERE accounts.id = NEW.account_id;
END IF;
END
我的脚本只在balance
表上进行插入,并从accounts
表中进行选择以获得余额。
问题:当PHP执行INSERT查询时,触发器不会被触发(或者不起作用)。但是,如果我从MySQL日志中复制查询并将其粘贴到MySQL的命令行客户端中,它确实有效,并且我得到了所需的结果(accounts
表得到了正确更新)。想法?
以防万一,所有查询都由Zend_Db_Table_Row的一个实例处理。
这个问题的解决方案再明显不过了。在插入到balance
表的同时,我的脚本也在更新accounts
表。现在,如果我使用框架中提供的Zend_Db_Table_Row
类,这不会是一个问题。但我很久以前就定制了它,将过滤器应用于集合中的每一行,就像这样(简化为这个答案):
class Mauro_Db_Table_Row extends Zend_Db_Table_Row {
// Pre-update logic
function _update() {
$data = $this->toArray();
$data = $filters->filter($data);
$this->setFromArray($data);
}
}
所以我把它改成了这个:
class Mauro_Db_Table_Row extends Zend_Db_Table_Row {
// Pre-update logic
function _update() {
$diffData = array_intersect_key($this->_data, $this->_modifiedFields);
$data = $filters->filter($diffData);
$this->setFromArray($data);
}
}
现在只有修改后的字段被过滤,$account->balance
保持不变。
我还向用户添加了一些列特定的REVOKE
语句,我的脚本正在使用这些语句来加倍敏感数据的安全屏障:p。