antonyz89/change-log-behavior

yii2模型的简单变更日志行为

1.2.4 2024-05-27 12:29 UTC

README

为你的yii2-models提供简单行为

Cranky4/change-log-behavior 分支而来

安装

1- 通过composer安装包

composer require antonyz89/change-log-behavior "*"

2- 运行迁移

yii migrate --migrationPath=@vendor/antonyz89/change-log-behavior/src/migrations

使用方法

1- 将 ChangeLogBehavior 添加到任何模型或活动记录

public function behaviors()
{
    return [
        ...
        [
            'class' => ChangeLogBehavior::className(),
            'db' => Yii::$app->other_db, # optional (default is the same as Yii::$app->db)
            'excludedAttributes' => ['updated_at'],
        ],
        ...
    ];
}

注意:行为仅监视“安全”属性。如果您不想记录其更改,请将属性添加到 excludedAttributes 中。

2- 将 ChangeLogList 添加到视图中

 echo ChangeLogList::widget([
     'model' => $model,
 ])

3- 添加自定义日志

$model->addCustomLog('hello world!', 'hello_type')

自定义字段

使用自定义字段,您可以在名为 custom_fields 的属性中存储额外的值。当您需要根据其他字段或关系生成值时,此功能非常有用。

public function behaviors()
{
    return [
        [
            'class' => ChangeLogBehavior::class,
            'autoCache' => true,
            'customFields' => [
                'total' => static function (self $model) {
                    return $model->calculateTotal();
                },
                // or static function (self $model) { return $model->createdBy->name; }
                'created_by' => 'createdBy.name'
            ]
        ]
    ];
}

在字段名称后使用 ! 强制保存,即使它没有更改。

public function behaviors()
{
    return [
        [
            'class' => ChangeLogBehavior::class,
            'autoCache' => true,
            'customFields' => [
                'total' => static function (self $model) {
                    return $model->calculateTotal();
                },
                // `user_id` will be registered even if it hasn't changed
                'user_id!' => 'user.name',
                'created_by' => 'createdBy.name'
            ]
        ]
    ];
}

工作原理

  • 在查找模型时,自定义字段被激活以缓存自定义字段的当前值。在保存模型时,自定义字段被重新生成以存储前后值。

    {
        "title": ["Hello World", "New Title"],
        "custom_fields": {
            "total": [50, 100]
        }
    }
  • 自动缓存自定义字段

    • 默认情况下 $autoCachefalse,自定义字段不会在触发 ActiveRecord::EVENT_AFTER_FIND 时缓存,以防止性能问题。
    • 调用 cacheCustomFields() 手动缓存自定义字段。
      class FooController extends Controller {
          // ...
      
          public function actionUpdate($id) {
              $model = $this->findModel($id);
              // cache custom fields manually
              // [[cacheCustomFields()]] is a magic method that calls [[ChangeLogBehavior::cacheCustomFields()]]
              $model->cacheCustomFields();
      
              $modelChildren = array_map(function () {
                  // imagine something cool here
              }, $this->request->post());
      
              foreach ($modelChildren as $modelChild) {
                  $modelChild->parent_id = $model->id;
                  $modelChild->save();
              }
      
              // on save the custom fields are computed again and saved if they changed
              $model->save();
          }
      }
    • 要启用 $autoCache,将其设置为 true,则自定义字段将在触发 ActiveRecord::EVENT_AFTER_FIND 时缓存。但请注意。

删除时保存数据

默认情况下,行为在删除时不保存数据。将 dataOnDelete 设置为 true 以在删除时保存数据。

/**
 *  @inheritdoc
 */
public function behaviors()
{
    return [
        [
            'class' => ChangeLogBehavior::class,
            'dataOnDelete' => true
        ]
    ];
}

结果将类似于

{
    "field_1": ["value", null],
    "field_2": ["value", null],
    "field_3": ["value", null],
}

最后值总是 null

dataOndelete = true 也会保存自定义字段。

父ID

为变更日志设置父ID。

这对于创建自定义的变更日志视图非常有用。

默认值: null,接受: null | string | callable

public function behaviors()
{
    return [
        [
            'class' => ChangeLogBehavior::class,
            // get `user_id` from model ($model->user_id)
            'parentId' => 'user_id', 
            // get `user_id` from model using static function
            'parentId' => static functiobn (self $model) {
                if ($model->type !== 'ADMIN')
                    return $model->user_id;
                }

                return null;
        ]
    ];
}

示例

模型 Post

/**
 * @propertu int id
 * @property int created_at
 * @property int updated_at
 * @property string title
 * @property int rating
 */
class Post extends yii\db\ActiveRecord {
    
    /**
     *  @inheritdoc
     */
    public function behaviors()
    {
        return [
            [
                'class' => ChangeLogBehavior::class,
                'excludedAttributes' => ['created_at','updated_at'],
                // (optional) autoCache is disabled by default
                'autoCache' => false,
                // (optional) - custom fields
                'customFields' => [
                    'total' => static function (self $model) {
                        return $model->calculateTotal();
                    },
                    // or static function (self $model) { return $model->createdBy->name; }
                    'created_by' => 'createdBy.name'
                ]
            ]
        ];
    }
}

视图 post/view.php

use antonyz89\ChangeLogBehavior\ListWidget as ChangeLogList;
use app\models\Post;

/**
 *  @var Post $model
 */
echo DetailView::widget([
    'model' => $model,
    'attributes' => [
        'id',
        'title',
        'rating',
        'created_at:datetime',
        'updated_at:datetime',
    ],
]);

echo ChangeLogList::widget([
    'db' => Yii::$app->other_db, # optional (default is the same as Yii::$app->db)
    'model' => $model,
]);