【问题标题】:Yii2 behavior : Dynamically attribute set valueYii2 行为:动态属性设置值
【发布时间】:2020-08-14 17:22:37
【问题描述】:

更新

我有一条使用 Yii 插入的记录 我的模型名为 Shipment,实现了:

 /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            [
                'class' => BlameableBehavior::className(),
            ],
            [
                'class' => TimestampBehavior::className(),
            ],
        ];
    }

假设这些是数据库中的记录,如下所示:

DATABASE (1:1)
+----+--------------------+--------------------+------------+------------+
| id | freight_created_at | freight_updated_at | created_at | updated_at |
+----+--------------------+--------------------+------------+------------+
| XX | NULL               | NULL               | 1597223608 | 1597315472 |
+----+--------------------+--------------------+------------+------------+

然后我需要更新另一个名为 freight_created_at & freight_updated_at 的列。这是因为在同一条记录中,所以我不能再次使用 EVENT_BEFORE_INSERT。

我对PUT货运的行动,目标是:

  1. 如果freight_created_at栏为空,请填写 freight_created_atfreight_updated_at
  2. 其他人只更新freight_updated_at

然后在 Yii2 中

控制器

public function actionPutFreightDitawarkan($id) {
   $model = $this->findModel($id);
   $model->scenario = Shipment::SCENARIO_FREIGHT_DITAWARKAN;
   $model->attachBehaviors([FreightDitawarkanTimestamp::class]);
   
   ... 

}

如果我想使用一个行为,我该如何实现它?到目前为止,行为看起来像这样。

行为

class FreightDitawarkanTimestamp extends AttributeBehavior {

    public $createdAtAttribute = 'freight_created_at';
    public $updatedAtAttribute = 'freight_updated_at';
    public $value;

    public function init() {
        if (empty($this->attributes)) {
            $this->attributes = [
                BaseActiveRecord::EVENT_BEFORE_UPDATE =>
                    [
                        $this->createdAtAttribute,
                        $this->updatedAtAttribute
                    ]
            ];
        }
        parent::init();

    }
    protected function getValue($event) {
        $this->value = date('Y-m-d H:i');
        return parent::getValue($event);
    }
}

【问题讨论】:

    标签: php yii2


    【解决方案1】:

    仅当您想在多个模型中使用该行为时才适合此处的行为,否则您可以只使用$model->touch()(即$model->touch('freight_created_at')),因为您可以通过已附加的 TimestampBehavior 访问该方法。

    但如果这是多模型案例,那么您的方法确实不错。我也会覆盖evaluateAttributes() 以满足您的要求,例如:

    public function evaluateAttributes($event)
    {
        if ($this->skipUpdateOnClean
            && $event->name == ActiveRecord::EVENT_BEFORE_UPDATE
            && empty($this->owner->dirtyAttributes)
        ) {
            return;
        }
    
        if (!empty($this->attributes[$event->name])) {
            $attributes = (array) $this->attributes[$event->name];
            $value = $this->getValue($event);
            foreach ($attributes as $attribute) {
                if ($attribute === $this->createdAtAttribute && !empty($this->owner->$attribute)) {
                    // don't update "created_at" value if already set
                    continue;
                }
                $this->owner->$attribute = $value;
            }
        }
    }
    

    getValue()可以简化为:

    protected function getValue($event)
    {
        return date('Y-m-d H:i');
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-24
      • 1970-01-01
      • 2011-11-02
      • 1970-01-01
      • 2013-02-19
      • 2013-06-18
      • 2011-02-18
      相关资源
      最近更新 更多