@AlexKuznec

Как передать значение свойства модели внутри её rules()?

От пользователя приходит его локальное время 'usertime' и часовой пояс 'timezone'.
Я сохраняю эти данные в базу, плюс хочу добавить время 'time' в UTC для удобства обработки.
Это потенциально позволяет сделать валидатор 'date' ( www.yiiframework.com/doc-2.0/yii-validators-dateva... )
Вот так я попытался прописать правила валидации:
public function rules()
    {
        return [
            [['usertime', 'timezone'], 'required'],
            [['timezone'], 'trim'],
            [['timezone'], 'string', 'max' => 255],
            [['usertime'], 'date', 'type' => 'datetime', 'timeZone' => $this->timezone, 'timestampAttribute' => 'time'],
            [['time'], 'required'],
        ];
    }


Проблема в том, что в данной функции $this->timezone почему-то содержит вместо свежих пользовательских данных часовой пояс из этой записи до обновления. Как будто $this->timezone подгружается из базы данных, используется, а затем происходит load() и в базу сохраняются все данные, введенные пользователем.
Есть какое-то решение, или надо заполнять 'time' в отдельном событии или поведении?
  • Вопрос задан
  • 115 просмотров
Решения вопроса 1
@AlexKuznec Автор вопроса
Так и не разобрался, почему данные в rules() подгружаются из базы, а не load(), может быть даже разработчикам напишу) ведь код в вопросе значительно красивей того, который работает.

В итоге добавлено поведение:
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();
                },
            ],
        ];
    }


И 'time' убрал из rules():
public function rules()
    {
        return [
            [['usertime'], 'date', 'type' => 'datetime'],
            [['usertime', 'timezone'], 'required'],
            [['name', 'timezone', 'period'], 'trim'],
            [['name', 'timezone', 'period'], 'string', 'max' => 255],
           ...
        ];
    }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
mhthnz
@mhthnz
PHP, YII2, Golang, Linux
Можно опробовать из контроллера достать валидаторы уже после загрузки данных в модель и установить тайм зону. Код не проверял, но примерно вот так:
$model = new Model;
if ($model->load(Yii::$app->request->post)) {
    $validators = $model->getValidators();
    foreach($validators as $validator) {
        // Ищем тут нужный нам валидатор даты и задаем ему тайм зону
        $validator->timeZone = $model->timezone;
    }
    $model->save();
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы