Какие минусы прописать все правила полей в AR модели Yii2?
Какие задачи решаю:
1. Проверка валидности данных перед сохранением в БД, неважно от юзера получили или криворукий программист собрал модель -надо проверить данные перед сохранением. Проверяем только поля что идут в БД, для всего остального используем модель форм которая должна собрать основную AR-модель чтоб она могла сохранится.
2. Не копи-пастить логику по разным моделям форм. Есть AR-модель Юзер, у него есть пароль, теперь правила пароля: форма регистрации, форма входа, форма смены пароля после восстановления, смена пароля в кабинете, смена пароля в админке (свой пароль), смена пароля в админке другого юзера и т.д. кучу кучу форм где идет копипаст правил. И теперь что делать если поставили задачу увеличить миним. кол-во символов в пароле или поставить еще проверку на сложность пароля?
Как я вижу решение:
1. БД не содержит никакой логики, тупо черный ящик, но модель перед ней решает все (последняя инстанция, отступать некуда позади... БД)
2. AR-модель самая тяжелая
2.1 содержит все правила по всем(!) полям БД. Защита от дураков и кривых рук, не сохраняется пока все по уму не сделаешь.
2.2 метод сценариев переписан так, что все поля небезопасны для load(). Контроллер говорит модели с какими полями можно работать, либо модель формы (наследница AR-модели) говорит с какими полями она работает. и только тогда load() работает
2.3 при save() запускаются валидаторы только для полей что были обновлены
Так, один раз написав по уму модель, можно раскидать задачи с этой моделью на других разрабов, которые напишут разные формы, разные API и я буду более-менее уверен, что в БД будут целые, валидные данные. Не говоря о том, что завтра не нужно будет поиском выковыривать места, где идет проверка данных для этой модели (поставили задачу сделать необязательным какое-то поле или сделать float вместо int).
Такое ощущение, что вы не разобрались в Yii2, но уже начали переписывать его "под себя". Если внешние ключи установлены в таблицах базы, Gii отличный код генерирует, со всеми связями и проверками. Я из правил только ссылку на узера заменяю поведением (BlameableBehavior), даты создания/обновления на TimestampBehavior, boolean надо подправить (gii его как integer подписывает) ну и небезопасные атрибуты пометить значком "!" (которые пользователь не имеет права присылать).
AlexKuznec: "которые пользователь не имеет права присылать" по всему сайту или с тек. страницы/формы? Если пользователю дают доп. права админа? Или, допустим, у нас две формы, в одной форме можно поменять Имя, в другой форме можно поменять пароль, если в одной из формы добавить в запрос поля другой формы, то модель обновит все поля? т.е. если модель разрешает менять свои атрибуты "скопом" юзерам ей нет смысла следить откуда эти данные? Мне было бы спокойнее если контроллер говорил с какими полями он работает, если работает напрямую с AR-моделью. Или модель Формы говорила AR-модели с какими полями она работает. А так разрешать скопом менять поля или раздувать метод сценариев как-то сложно. Всегда помнить надо, всегда следить.
"которые пользователь не имеет права присылать" - это атрибуты, которые не будут массово присвоены, но будут проверены на правильность, то есть метод load() и подобные не смогут их изменить, только "вручную" в контроллере (или модели) надо будет прописывать что-то вроде $model->nameOfAttribute = $value; не важно, откуда данные взялись, хоть из базы вы их загрузите, модель это не волнует) В вашем случае вроде как сценарии наиболее подходят, если есть несколько вариантов менять поля. Если очень хочется, можно вручную атрибуты присваивать вместо load() :)
AlexKuznec: проблема в другом, наверно все таки я не так описываю. Простой вопрос: Какие правила можно/надо прописать в AR-модели? Именно AR-модели, например, User или Post, а не UserCreateForm. Все что я пропишу в AR-модели по-умолчанию становятся безопасными атрибутами! И если я построю форму от такой модели, то пользователь сможет поменять все поля
Arik: нет, только атрибуты, указанные для текущего сценария, будут безопасными. По умолчанию сценарии генерируются через правила, указанные в rules(). Но можно и вручную прописать в виде массивов в scenarios(). Если в rules() указать [['name', 'phone', '!admin'], 'string'], то только 'name' и 'phone' будут загружены через load()
если имеются атрибуты вроде 'created_at' и 'updated_at', но они не указаны в rules или текущем сценарии, то они тоже не будут загружаться, но могут быть установлены поведением, прицепленным к модели, или указаны вручную: $model->updated_at = time();
Arik: прекрасно работает) он как раз указывает, чтобы данный атрибут не помещался в сценарий. А сценарии, насколько я понял, это всего лишь списки безопасных атрибутов, которые сужают список из rules().
AlexKuznec: да, действительно "!" работает и в rules, в доках или нет или я упустил как-то. Получается я могу в AR-модели прописать все правила для модели и пометить их как небезопасные, тогда формы должны будут явно указать эти поля или через сценарий работать, но save будет проверять все поля, что я и хотел. Спасибо!
Вроде как ActiveRecord и реализует всё это: проверка поступающих значений, сценарии для контроля, когда какие атрибуты могут быть изменены.
save(), кажется, тоже сохраняет только изменившиеся значения (можете покопаться в исходниках или документации, так как я в этом месте глубоко не копал).
Как образец, можете посмотреть реализацию регистрации и логинов (несколько форм и контроллеров) в приложении advanced.