Multiple Select Validation

I have search form with multiple select and want to validate each of selected option via RangeValidator in search model. This code doesn’t work:




    public function rules()

    {

        return [

            [['status_id'], 'in', 'range' => [1, 2, 3],

        ];

    }



How can I apply validators to array values?

Seems some type issue can you try with this (the strict option):




    public function rules()

    {

        return [

            [['status_id'], 'in', 'range' => [1, 2, 3], 'strict' => true],

        ];

    }



In addition, also check what your return values are for your select element (assuming you are using Html::dropDownList or Html::listBox). The list source data should be an associative array:


[1 => 1, 2 => 2, 3 => 3]

.

If you are passing


[1, 2, 3]

as the list source then the keys may be taken as 0, 1, 2 internally.

‘strict’ is for type comparison.

I pass an array of id => name to listBox. When I submit form, I see this in $_GET (I use get method):


status_id

[

    0 => '1'

    1 => '2'

]

This does not match what you have in your model [font="Courier New"]IN / RANGE[/font] validation. You may want to debug this… it should ideally return


[1 => '1', 2 => '2']

Yes… if you are passing the string ‘3’ instead of integer 3 and wish to validate based on integer type strictly.

No, it shouldn’t. When you have select with name ‘status_id[]’, you will get an indexed array of selected options values in POST/GET. For example, if you use get method, you will get this uri:

order/index?status_id%5B%5D=1&status_id%5B%5D=2

I think you misunderstand my problem. If I use this validation with normal select (not multiple), everything works fine. But I want to write validation rule which will work for an array of values (from multiple select) - not for just integer or string in status_id attribute.

Let me describe my problem in other words.

You have model Order with attribute status_id. This attribute must have only one of this values: [1, 2, 3]. You want to make search model and form with multiple select tag, which correspond to status_id attribute. What validation rule will you use for status_id to allow multiple values (to use Order::find()->andFilterWhere([‘in’, ‘status_id’, $this->status_id])) and validate each of them against an array [1, 2, 3]?

I see. I get your problem now.

IMO the range validator does not validate an array of inputs. You may try implementing a custom validator in your model like below:




public function checkRangeValid() {

    if (!$this->hasErrors()) {

        $statuses = !is_array($this->status_id) ? [$this->status_id] : $this->status_id;

        $allowed = [1, 2, 3]; // the allowed list

        foreach ($statuses as $status) {

            if (!in_array($status, $allowed)) {

                $this->addError('status_id', "Invalid status '{$status}' in the list");

                break;

            }

        }

    }

}



Then in your model rules you can set:




public function rules()

{

    return [

        [['status_id'], 'checkRangeValid'],

    ];

}



So Yii doesn’t have any out-of-box solution for validating array elements? Isn’t it a common situation when you need to validate values from multiple select?

Think so presently. You can try recording an issue on github for enhancement.

Yes, I will create an issue. Thanks for participate.