5

我正在创建一个审计跟踪模块,我将把它放在一个更大的系统中;我创建了一个表来存储跟踪条目,作为“审计员”,我想查看当前登录的用户、他/她所在的页面、他/她做了什么动作以及发生了什么变化什么时候...

这些基本上是我想看到的;我的审计跟踪表如下所示:

用户| 时间戳| 模块名称| 行动| 旧值| 新价值| 描述

我基本上没有问题,通过

Yii::app()->session['username'];

通过获取控制器的页面/模块和操作:

$this->module->getName();
$this->action->id;

我的问题在于将旧值更改为新值,即用户所做的编辑。我可以通过逐字复制变量并将其传递给我创建日志的函数来“嗅出”他/她所做的编辑/更改。我如何动态地做到这一点?

我有点想检测某个模型的属性或属性是否已更改,并查看进行了哪些更改,以便我可以获得详细日志...谢谢!对不起,我真的很努力解释这一点。

4

3 回答 3

8

在您想要观察的每个模型中,您可以编写一个afterFind()方法,将当前数据库属性存储到某个私有变量 eb_dbValues中。然后,beforeSave()您验证当前属性与其中的属性,_dbValues并在发生更改时创建审核记录。

完成此工作后,您可以更进一步并从中创建行为。您将私有变量, theafterFind()beforeSave()方法放在那里。然后,您可以将该行为附加到许多记录。

于 2013-05-22T07:33:44.323 回答
6

快速示例:

class Book extends CActiveRecord
{
    private $oldAttrs = array();

    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }

    public function tableName()
    {
        return 'book';
    }

    protected function afterSave()
    {
        // store history
        if (!$this->isNewRecord) {
            $newAttrs = $this->getAttributes();
            $oldAttrs = $this->getOldAttributes();

            // your code
        }

        return parent::afterSave();
    }

    protected function afterFind()
    {
        // Save old values
        $this->setOldAttributes($this->getAttributes());

        return parent::afterFind();
    }

    public function getOldAttributes()
    {
        return $this->oldAttrs;
    }

    public function setOldAttributes($attrs)
    {
        $this->oldAttrs = $attrs;
    }
}
于 2013-05-22T07:47:09.140 回答
0

您的解决方案很好,但是如果有 2 个线程同时调用 ->save() 怎么办?

假使,假设:

  1. 第一个线程找到记录,保存A状态。
  2. 第二个线程查找记录,保存A状态。
  3. 然后第一个线程将记录更改为 B,调用 ->save()。系统将记录 A->B
  4. 然后第二个线程将记录更改为 C,调用 ->save()。系统将记录 A->C

总结,有2个日志:A->B,A->C。如果这对您来说不是问题,请忽略它并执行上述解决方案。

于 2013-05-23T08:32:41.810 回答