Hello everyone, please consult everyone. Validation is usually placed in ‘activeRecord’ in the project, but in order to avoid polluting the original ‘model’ when there are additional attributes, a new “ValidateForm” is written. However, in the process of writing code, May accidentally call mode->save() directly and “forget” to use “validateForm”, is there any good method or experience to avoid this problem?
For example, a Person extends CActiveRecord, with very basic validation rules.
And a special form for the frontend, FrontendPerson extends Person, with scenario specific rules and additional properties.
Then a new colleague goes working with Person class but never uses FrontendPerson. Or you create a console command for Person stuff, which actually should use FrontendPerson (or BackendPerson).
I think you can easily force using ‘form classes’ by defining the real Person as abstract.
But you should define that in realations too then. For example a Post has relations with Person, they should refer to your FrontendPerson, or BasicPersonForm. Because abstract classes may not be instantiated directly.
And/or create a proper directory structure, where you have dir with forms which always have forms for all your models (the database layer). That way you can always regenerate your models without effecting the forms with additional methods and properties. Your code generator also has to be customized if you want to rely on ‘form’ classes and have ‘abstracted’ your active records.
Yes, there are two classes, one is the basic ProductModel, and the other is the product form (extend from product model). In order to prevent programmers from directly using the ProductModel for verification, we want to prohibit the ProductModel()->validate () operation, but we must use the ProductForm for form data entry.
@wangzhoubin well, is the ProductModel defined as abstract class ProductModel extends ActiveRecord ?
Then none is allowed to directly use the ProductModel and you are forced to create a Form subclass.
Keep in mind then that model relations also should point to the Forms then, if you go with this route.
I may have understood that when saving () is executed, if rules()=>[] returns an empty array, save(true) will not contain any data that needs any verification.
Look into /base/Model.php, function setAttributes().
Attributes that are not ‘safe’ are not massively assigned. And therefore not saved. But if you set them yourself per attribute, they are saved.
Depending on your usage, you can leave rules() empty, or override safeAttributes() to return no or all attribute names.
I prefer:
PersonModel extends ActiveRecord
With basis validation for ALL fields (but as less ‘required’ rules as possible).
For example name length max 255.
This can be abstract, if you adjust all usages accordingly
ScenarioSpecificForm extends PersonModel
With only scenario specific rules, rules() merges with parent::rules() !
For example name required, name min length 32
safeAttributes() returns the attributes to be massively assigned for this scenario.
But:
this is based on my Yii1 experience, have only a few hours experience with Yii2.
This is a very good way. However, the ProductModel can’t be instantiated, so if you want to modify the properties by non-form verification, such as: ProductModel::findOne (),
only use ProductForm::find () , and there are many common operations, such as $product-> updatestatus (), $product->updateOnline() ,...