@tekord
Веб-разработчик

Как лучше реализовать повторнуб валидацию формы, поля которой конвертируются из строки в \DateTime?

Допустим, есть модель:

class ProductDatesCheckerForm extends Model {
       const INPUT_DATE_TIME_FORMAT = "d.m.Y H:i";

	/**
	 * @var string
	 */
	public $startDateTime;

	/**
	 * @var string
	 */
	public $endDateTime;

	/**
	 * @var array
	 */
	public $productReferences = [];

	/**
	 * @inheritDoc
	 */
	public function rules() {
		return [
			[['startDateTime', 'endDateTime', 'productReferences'], 'required'],
			[['startDateTime', 'endDateTime'], 'datetime', 'format' => self::INPUT_DATE_TIME_FORMAT],
			[['productReferences'], 'safe']
		];
	}
}


Как видно из правил валидации, для полей времени указан формат. После того как модель провалидирована, я хочу преобразовать все даты в объект \DateTime, чтобы использовать эти значения в вычислениях. Чтобы не плодить дополнительные объекты я преобразую даты прямо в этой модели, заменяю исходные текстовые значения на объект типа \DateTime. Однако, если я провалидирую модель, то будет ошибка, ведь поля не соответствуют требоемому формату.

Вопрос: как мне организовать всё так чтобы после преобразования дат в \DateTime небыло проблем с валидацией? Конечно, вызывать валидацию имеет смысл только в начале, после загрузки модели, но всё же, чисто академический интерес.

Первая идея была добавить when для datetime валидатора, но эта функция принимает только $model, и нет ссылки на валидатор для которого идёт проверка, чтобы посмотреть какие атрибуты валидируются. Именованое правило валидации (`'myDates' => [['startDateTime', 'endDateTime'], 'datetime' ...'`) тоже не подходит, т.к. при первом вызове валидации инстнцируются валидаторы из rules(), метод Model::createValidators не учитывает ключи в массивах rules(). Соответственно, нет возможности получить конкретный валидатор в рантайме.

Вторая идея - добавить поле-флажок $isConverted, и в when проверять значение. Если true, то игнорировать валидацию.
  • Вопрос задан
  • 172 просмотра
Решения вопроса 1
mitaichik
@mitaichik
Вы можете написать кастомный валидатор, в котором будете проверять тип и валидировать в зависимости от него.

Но хранить в одном поле данные в разных типах - это очен очень плохая идея. Аукнеться огромными проблемами в будущем. Лучше сделайте пару методов которые будут конвертит в DateTime. Или держите в полях только DateTime, и конвертите строки во время заполнения данных.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
slo_nik
@slo_nik Куратор тега Yii
Доброе утро.
Попробуйте так:
['startDateTime', 'datetime', 'timestampAttribute' => 'startDateTime', 'format' => self::INPUT_DATE_TIME_FORMAT],

yii\validators\DateValidator
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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