【问题标题】:Detecting changes in the model; php yii framework检测模型的变化; php yii 框架
【发布时间】:2013-05-17 02:01:17
【问题描述】:

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

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

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

我基本上没有问题获得用户,通过

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

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

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

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

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

【问题讨论】:

    标签: php model yii controller audit


    【解决方案1】:

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

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

    【讨论】:

    • afterFind 将在每次查找后进行评估,就像在网格中一样,对吧?也许场景可以用于将属性存储到 _dbValues 仅在更新时。
    • 谢谢!这很有用:D
    【解决方案2】:

    快速示例:

    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;
        }
    }
    

    【讨论】:

    • 谢谢..我会试试这个
    【解决方案3】:

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

    假设:

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

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

    【讨论】:

      猜你喜欢
      • 2013-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多