Страница 1 из 1

CRangeValidator баг или фича

Добавлено: 2013.06.11, 15:40
6pblcb
Есть првило валидации:

Код: Выделить всё

array('attribute', 'in', 'allowEmpty'=>false, 'range' => array(0,1,7,13), 'enableClientValidation' => false),
 
Если из формы получаем: то правило валидации отрабатывает без ошибок.

Отсюда и вопрос: верно ли поведение валидатора?

Re: CRangeValidator баг или фича

Добавлено: 2013.06.11, 15:50
anton44eg
подозреваю, что приведением типов из '' получается 0

Re: CRangeValidator баг или фича

Добавлено: 2013.06.11, 15:52
Nafania
Верно, потому что используется in_array, а у него не строгая проверка по умолчанию, соотв. '' == 0.
Используйте strict

Re: CRangeValidator баг или фича

Добавлено: 2013.06.11, 16:04
6pblcb
strict не совсем работает)
Пустое значение теперь невалидно (отрабатывает верно), зато "ноль" в контексте формы мы получаем значение и это опять невалидно.

Re: CRangeValidator баг или фича

Добавлено: 2013.06.11, 16:19
Nafania
Верно, делайте приведение к типу жесткое. геттер и сеттер на этот атрибут. Тут или или.

Re: CRangeValidator баг или фича

Добавлено: 2013.06.11, 17:13
6pblcb
Спасибо. Как работает этот валидатор я разобрался ещё до того как писать на форум.
Для некоторых случаев более простым решением будет, обернуть 0 в кавычки:

Код: Выделить всё

array('attribute', 'in', 'allowEmpty'=>false, 'range' => array('0',1,7,13), 'enableClientValidation' => false),
 
Но вот если требуется большой диапазон, 'range' => range(-100, 500).....
Мне недает покоя 'alllowEmpty'=>false. Ведь этот пораметр по идее и должен исключать ситуацию пустого значения. Эдакий такой микс range и required. В коде валидатора как раз на первом месте стоит проверка на empty, но вот она имеен обратный смысл т.е. проверка больше "на валидность без ошибки".

Код: Выделить всё

$value=$object->$attribute;
if($this->allowEmpty && $this->isEmpty($value))
    return;
... дальше проверка на range...
По моему логично если 'allowEmpty'=>false, проверить сначала на empty и если невалидно, то выдать ошибку.

Re: CRangeValidator баг или фича

Добавлено: 2013.06.11, 17:51
AlexSimp
Есть в ваших рассуждениях логика, но что если в диапазоне значений надо будет учитывать пустое значение?

Код: Выделить всё

'range' => array('','a','b','c')
 
Это ведь вполне реальная ситуация, например при использовании группы чекбоксов.

allowEmpty по логике предназначен для проверки отсутствия аттрибута как такового, а проверка пустоты переданного значения -- это уже дополнительная плюшка, именно поэтому в коде все так и происходит (ИМХО)

Re: CRangeValidator баг или фича

Добавлено: 2013.06.11, 18:44
alekso
может быстрей и легче свой валидатор написать?

Re: CRangeValidator баг или фича

Добавлено: 2013.06.12, 07:40
6pblcb
allowEmpty по логике предназначен для проверки отсутствия аттрибута как такового...
Не совсем понял, что Вы имеете в виду =\
может быстрей и легче свой валидатор написать?
В этом вопрос вообще не стоит ;) Мне просто интересно услышать "чужое" мнение по логике работы этого валидатора.

Ещё чуть-чуть мыслей:)
Исходя из описания параметра из allowEmpty

Код: Выделить всё

whether the attribute value can be null or empty. Defaults to true, meaning that if the attribute is empty, it is considered valid. 
и логики работы функции isEmpty и её описания

Код: Выделить всё

/**
     * Checks if the given value is empty.
     * A value is considered empty if it is null, an empty array, or the trimmed result is an empty string.
     * Note that this method is different from PHP empty(). It will return false when the value is 0.
     * @param mixed $value the value to be checked
     * @param boolean $trim whether to perform trimming before checking if the string is empty. Defaults to false.
     * @return boolean whether the value is empty
     */
    protected function isEmpty($value,$trim=false)
    {
        return $value===null || $value===array() || $value==='' || $trim && is_scalar($value) && trim($value)==='';
    }
думаю такой код для validateAttribute имеет место быть:

Код: Выделить всё

protected function validateAttribute($object,$attribute)
{
$value=$object->$attribute;
if($this->isEmpty($value))
{
    if(!$this->allowEmpty)
    {
        $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} cannot be blank.');
        $this->addError($object,$attribute,$message);
    }
    return;
}
...etc...
update:
Кстати clientValidateAttribute на сколько я понимаю работает корректно т.е. value = '' невалидно.

Re: CRangeValidator баг или фича

Добавлено: 2013.06.12, 11:06
samdark
Очень похоже на баг.

Re: CRangeValidator баг или фича

Добавлено: 2013.06.12, 13:11
samdark
https://github.com/yiisoft/yii/pull/2554 пока только тесты. На тему фикса не уверен.

Re: CRangeValidator баг или фича

Добавлено: 2013.06.12, 14:00
samdark
Фикснуто, код пока можно посмотреть в diff реквеста. Замечания приветствуются.

Re: CRangeValidator баг или фича

Добавлено: 2013.06.12, 19:17
6pblcb
Неожиданно) Очень оперативно, спасибо)

Re: CRangeValidator баг или фича

Добавлено: 2013.06.12, 21:40
samdark
Намёржили. Будет в 1.1.14.