Model class rules() method

As per the Yii2 docs the validation rules can be applied either to the implicit properties (table fields) or to the userDefined properties.

Is there a way to create validation rules for the properties which are dynamically added to the model class?

Hi!

I would say the answer depends on what exactly you mean with:

"dynamically added to the model class"?

Could you give a quick example what exactly you are trying to achieve?

Regards

For example:

Let there be model class named ‘Filter’ and another model class named ‘Category’ - categories like laptop, palmtop, desktop etc. I may want to use trackpad area as one of the filter to category laptop and diagonal length as one of the category to palmtop and so on. So in every case filter conditions vary according to the category I choose and I may want to add it to the model class Filter dynamically and a validation if the load via post was successful.

Got the below response from stack overflow and resolved this issue,

You can code the rules()-function to build an array of validation rules depending on the scenario and data input. It is not a requirement that this is a fixed array. Unfortunately doing it this way will leave you with validation issues on the frontend (should you need that), dynamic rules there don’t work so well.

From the comments I gather that the biggest issue seems to be that the attributes are not loaded into the model. This is mainly because both load() and setAttributes() only fill attributes considered to be safe.

There are 2 methods to define an attribute as safe:

Give it a validation rule (at the very least safe)

Get it in the list of attributes returned by safeAttributes() (by overriding it)

hey, it’s really easy. There is my solution:




    public $properties = [];


    public function __set($key, $value)

    {

        $this->$key = $value;

        $this->properties[] = $key;

    }


 public function rules()

    {

        $array= $this->properties;

           return [

            [$testArray, 'integer','max'=>100,'min'=>0],

            [$testArray, 'required'],

            [$testArray, 'someMethod'],


        ];

    }


  public function someMethod($attribute, $params){

  $count = 0;

  foreach ($this->properties as $property) {

            $count += $this->$property;

        }

  if ($count > 100) $this->addError($attribute,"Sum of properties must be lower than 100")

}



enjoy :)

@ajayvembu, could you share the link for your question on Stack Overflow?

Stackoverflow link:

@ajayvembu, would you mind sharing your working code ? I have the same issue which depends on what dropdown value is, certain fields (dynamic) will show up. I m struggling with

  • how to add dynamic attributes to an existing ActiveRecord ?

  • how to add dynamic validation to above attributes ?

Maybe share your code and we can help. The above quote you made explains how to solve his issue.

This is how I have overridden the safeAttributes() method in the Model class I use.

I am returning all the string of attributes(that is the attributes which I have added to the model class dynamically) in the overridden method.


public function safeAttributes(){

	  

	  $query = 'select attribute_name from filter join item_attributes on filter.attribute_id=item_attributes.attribute_id where sub_category_id='.$this->sub_category_id_for_safe_check;

	  

	  $attribute_names = FilterItemAttr::findBySql($query)->orderBy('attribute_name')->all();

	  

	  $attributeArray = array();

	  

	  $i=0;

	  

	  foreach($attribute_names as $attribute_name){

	  	$attributeArray[$i++] = $attribute_name->attribute_name;

	  }

		

	  return $attributeArray;

	}

Thanks.