Обновлять атрибут модели `create_at`, только если он нулевой или пустой

Я использую расширенный шаблон приложения YII2 с пользователем yii2.

public function behaviors()
{
    return [
        TimestampBehavior::className(),
    ];
}

Это установит текущее значение timestamp в моей пользовательской модели. Но я хочу добавить это, только если это null; он не должен перезаписываться, если я устанавливаю значение в своем контроллере.


person vinod27ece    schedule 03.07.2015    source источник


Ответы (3)


Вы можете создать свой TimestampBehavior с пользовательской логикой:

<?php
namespace app\behaviors;

use yii\db\ActiveRecord;
use yii\base\Behavior;
use yii\db\Expression;

class ARTimestampBehavior extends Behavior
{

    public function events()
    {
        return [
            ActiveRecord::EVENT_BEFORE_INSERT => 'beforeInsert',
            ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeUpdate',
        ];
    }

    public function beforeInsert($event)
    {
        $model = $event->sender;
        if ($model->hasAttribute('created_at') && is_null($model->created_at)) {
            $model->created_at = new Expression('NOW()');
        }
        if ($model->hasAttribute('updated_at')) {
            $model->updated_at = new Expression('NOW()');
        }
    }

    public function beforeUpdate($event)
    {
        $model = $event->sender;
        if ($model->hasAttribute('updated_at')) {
            $model->updated_at = new Expression('NOW()');
        }
    }

}

А затем используйте его в своей модели:

public function behaviors()
{
    return [
        ARTimestampBehavior::className(),
    ];
}
person stepozer    schedule 03.07.2015
comment
Спасибо, попробую, а потом сообщу. - person vinod27ece; 03.07.2015

Я не думаю, что есть простой способ сделать это. Самый близкий из них можно получить без особого кодирования, чтобы указать пользовательское значение, которое нужно установить.

public function behaviors()
{
    return [
        [
            'class' => TimestampBehavior::className(),
            'value' => function($event) {
                return (/* some condition */)
                    ? your_custom_function_returning_the_time()
                    : time();
        ],
    ];
 }

При этом я рассматриваю это как потенциальное неправильное использование TimestampBehavior. Возможно, было бы лучше определить новый столбец для вашей пользовательской метки времени создания.

Если вы настроены на использование текущего столбца, откажитесь от TimestampBehavior и перезапишите метод beforeSave вашей модели:

public function beforeSave($insert)
{
    if (! parent::beforeSave($insert)) {
        return false;
    }
    if ($insert && this->create_at === null) {
        $this->create_at = time();
    }
    $this->update_at = time();
    return true;
}
person tarleb    schedule 03.07.2015
comment
Привет, в вашем подходе мне нужно изменить функцию beforeSave() в каждой из моих моделей? - person vinod27ece; 03.07.2015
comment
Да, поэтому, если у вас есть более одной модели, для которой вам это нужно, я бы сказал, что ответ @stepozer лучше того, что я предлагал. - person tarleb; 03.07.2015
comment
да, спасибо за ваш быстрый ответ. Я попробовал метод @stepozer, и он работает как шарм. - person vinod27ece; 03.07.2015

Просто используйте TimestampBehavior по умолчанию следующим образом:

/**
 * @inheritdoc
 * @return array mixed
 */
public function behaviors()
{
    return [
        'timestamp' => [
            'class' => TimestampBehavior::class,
            'createdAtAttribute' => 'created_at',
            'updatedAtAttribute' => false,
            'value' => function($event) {return $event->sender->created_at ?? new \yii\db\Expression('NOW()');},
        ],
    ];
}
person Zbigniew Szczęsny    schedule 06.02.2019