Yii2: Boolean validator generates incorrect error message

Created on 29 Mar 2016  路  11Comments  路  Source: yiisoft/yii2

What steps will reproduce the problem?

$validator = new \yii\validators\BooleanValidator([
    'trueValue' => true,
    'falseValue' => false,
    'strict' => true
]);
$validator->validate('someIncorrectValue', $errorMessage);
var_dump($errorMessage);

What is the expected result?

string(49) "the input value must be either "true" or "false"."

What do you get instead?

string(41) "the input value must be either "1" or ""."

Additional info

| Q | A |
| --- | --- |
| Yii version | 2.0.6 |
| PHP version | 5.5.9 |
| Operating system | Ubuntu 14.04 |

bug

Most helpful comment

But it's not correct in massages

All 11 comments

I'll fix it now

I don't think it is a bug. quotes are missing as values should be string. PHP's true/false are converted to '1' and '' :

$validator = new \yii\validators\BooleanValidator([
    'trueValue' => 'true',
    'falseValue' => 'false',
    'strict' => true
]);

see http://stackoverflow.com/questions/11921690/why-doesnt-php-print-true-false.

But it's not correct in massages

maybe but that is how PHP works. how would I expect true to be converted to 'true' when echo true; outputs 1. how can I tell : set trueValue and falseValue to whatever is considered native true and false in PHP ?

Here key significance 'strict' => true and it not apply to echo;

If you set parameters different from the String for the Validator, then the message is likely to be used only in logs. Because the $POST data is String values from Web. Therefore, the error message should be conditional, but correct.

exactly I set 'strict' to PHP's true while I expect 'trueValue' to receive a string with value 'true'. it is different. what if I'm saving that to a MySQL BIT(1) column I may set the attribute to true as I know PHP will send 1 instead ? what if I'm doing a POST with a javascript true expecting it to be converted to a string 'true' and figure out later that it was same as sending 1. you don't think it may confuse people ?

A value of model is valid always by:

$nonStrictValidator = new BooleanValidator([
            'trueValue' => true,
            'falseValue' => false,
            'strict' => false,
        ]);

and the message error will not throw never. Because I guess it will be used for the internal code only and messege error the input value must be either "true" or "false" is more correct in this case.

Fixed in 91bc1b5

Oh !! you meant only changing the error message output !! Sorry @githubjeka I guess I've been reading all backwards ! I definitively need some rest.

@tunecino np .. You made me think about a necessity in this validator and his behavior.
@samdark @SilverFire
To avoid such ambiguities here you could be remove strict param of the validator in v2.1.

class BooleanValidator extends Validator
{
    /**
     * @var string the value representing true status. Defaults to '1'.
     */
    public $trueValue = '1';
    /**
     * @var string the value representing false status. Defaults to '0'.
     */
    public $falseValue = '0';

    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();

        if (!is_string($this->trueValue) || !is_string($this->falseValue)) {
            throw new InvalidConfigException();
        }

        if ($this->message === null) {
            $this->message = Yii::t('yii', '{attribute} must be either "{true}" or "{false}".');
        }
    }

    /**
     * @inheritdoc
     */
    protected function validateValue($value)
    {
        $valid = ($value === $this->trueValue || $value === $this->falseValue);

        if (!$valid) {
            return [$this->message, [
                'true' => $this->trueValue,
                'false' =>$this->falseValue,
            ]];
        }

        return null;
    }

    /**
     * @inheritdoc
     */
    public function clientValidateAttribute($model, $attribute, $view)
    {
        $options = [
            'trueValue' => $this->trueValue,
            'falseValue' => $this->falseValue,
            'message' => Yii::$app->getI18n()->format($this->message, [
                'attribute' => $model->getAttributeLabel($attribute),
                'true' => $this->trueValue,
                'false' => $this->falseValue,
            ], Yii::$app->language),
        ];
        if ($this->skipOnEmpty) {
            $options['skipOnEmpty'] = 1;
        }

        $options['strict'] = 1;

        ValidationAsset::register($view);

        return 'yii.validation.boolean(value, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');';
    }
}

or remove this validator :hocho: and use RangeValidator

Was this page helpful?
0 / 5 - 0 ratings