A
A
AlexKuznec2016-10-13 18:15:27
Yii
AlexKuznec, 2016-10-13 18:15:27

How to pass the value of a model property inside its rules()?

From the user comes his local time 'usertime' and timezone 'timezone'.
I store this data in the database, plus I want to add the 'time' in UTC for ease of processing.
This potentially allows you to make a 'date' validator ( www.yiiframework.com/doc-2.0/yii-validators-dateva... )
This is how I tried to write the validation rules:

public function rules()
    {
        return [
            [['usertime', 'timezone'], 'required'],
            [['timezone'], 'trim'],
            [['timezone'], 'string', 'max' => 255],
            [['usertime'], 'date', 'type' => 'datetime', 'timeZone' => $this->timezone, 'timestampAttribute' => 'time'],
            [['time'], 'required'],
        ];
    }

The problem is that in this function, $this->timezone for some reason contains the time zone from this entry before the update instead of fresh user data. It's like $this->timezone is loaded from the database, used, and then load() happens and all the data entered by the user is saved to the database.
Is there a solution, or do I need to populate 'time' in a separate event or behavior?

Answer the question

In order to leave comments, you need to log in

[[+comments_count]] answer(s)
A
AlexKuznec, 2016-10-14
@AlexKuznec

I still haven’t figured out why the data in rules() is loaded from the database, and not load(), maybe I’ll even write to the developers) because the code in the question is much more beautiful than the one that works.
As a result, the following behavior has been added:

public function behaviors()
    {
        return [
            [
                'class' => AttributeBehavior::className(),
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => 'time',
                    ActiveRecord::EVENT_BEFORE_UPDATE => 'time',
                ],
                'value' => function ($event) {
                    // время устанавливается исходя из выбранного пользователем часового пояса
                    $model = $event->sender;
                    $datetime = new DateTime($model->usertime, new DateTimeZone($model->timezone));
                    return $datetime->getTimestamp();
                },
            ],
        ];
    }

And removed 'time' from rules():
public function rules()
    {
        return [
            [['usertime'], 'date', 'type' => 'datetime'],
            [['usertime', 'timezone'], 'required'],
            [['name', 'timezone', 'period'], 'trim'],
            [['name', 'timezone', 'period'], 'string', 'max' => 255],
           ...
        ];
    }

A
Andrew, 2016-10-13
@mhthnz

You can try to get validators from the controller after loading the data into the model and set the time zone. I didn't check the code, but something like this:

$model = new Model;
if ($model->load(Yii::$app->request->post)) {
    $validators = $model->getValidators();
    foreach($validators as $validator) {
        // Ищем тут нужный нам валидатор даты и задаем ему тайм зону
        $validator->timeZone = $model->timezone;
    }
    $model->save();
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question