Validation error - Value must be a string

Hello! I am new to Yii framework, so I am not sure how to deal with this small problem I have been stuck on for more than a day.

So my problem is that I want to store some data in the database, but it fails on calling save(), and the only way I can get it to work is by disabling validation, but I want to do it with validation.

The error message I get from calling getErrors() is as in the title ‘Value must be a string’. So I am trying to typecast the necessary value through validation.

In the docs I found this - https://www.yiiframework.com/doc/api/2.0/yii-validators-stringvalidator#$strict-detail

So I try to use it through rules()

public function rules(): array
{
    return ArrayHelper::merge(
        parent::rules(),
        [
            ['value', 'string', 'strict' => false],
        ]
    );
}

This is the part where I try to store the data into the database

public function setHasTransitArrival($value = true)
{
    $meta = MetaInformation::findOne([
        'remote_table' => self::tableName(),
        'remote_id' => $this->id,
        'field' => self::META_HAS_TRANSIT_ARRIVAL,
    ]);
    if ($meta === null) {
        $meta = new MetaInformation();
        $meta->remote_table = self::tableName();
        $meta->remote_id = $this->id;
        $meta->field = self::META_HAS_TRANSIT_ARRIVAL;
    }
    $meta->value = $value ? 1 : 0;
    $meta->validate();
    $meta->save();
}

The way it is written now does not change anything.
I expected it to validate the $value variable and cast it to ‘string’, and by adding " ‘strict’ => false " I expect it to accept scalar values and convert them accordingly.

Could someone, please, point out what do I not understand correctly or what am I doing wrong?

Ieliec pēdiņās $value ? ‘1’ : ‘0’;

Hi @mrzalais, welcome to the forum.

Is value really a string? If so, @uldisn’s suggestion should work, I guess.
But if it is not a string, e.g. an integer, then you should consider modifying the validator.

And, do you really need to validate it? I mean, does value's value come from a user input? If it is always given by program logic, then you won’t need to validate it at all.

Hey @softark. Thanks for the response. But I am required to use validation in this case. I am trying to do it with stringValidator in rules(), but not sure what am I doing wrong still. I’ve added this

[‘value’, StringValidator::class, ‘strict’ => false],

And it is not working, keep rereading the docs, but it is still not clear to me.

What is interesting is that I wrote a working validation now, but it works only if I write

    $meta->validate();
    $meta->save(false);

instead of

    $meta->save();

As I understand the validation in both cases is the same, but something seems to be throwing it off in the second case.

EDIT: Nevermind. I was trying to validate the wrong object.

@softark maybe you could help me with this?
I am trying to override the parent rules(), which are:

public function rules()
{
    return [
        [['remote_table', 'remote_id', 'field'], 'required'],
        [['remote_id'], 'integer'],
        [['remote_table', 'field', 'value'], 'string', 'max' => 255]
    ];
}

by merging them together in the child class

public function rules()
{
    return ArrayHelper::merge(
        parent::rules(),
        [
            [['value'], 'string', 'strict' => false]
        ]
    );
}

The problem is that ‘value’ is already defined in the parent class so the ‘strict’ => false does not work. Can’t find anything on how to properly override that.

Not very elegant, but I would do it like this if I had been forced:

public function rules()
{
 //   return ArrayHelper::merge(
 //       parent::rules(),
 //       [
 //           [['value'], 'string', 'strict' => false]
 //       ]
 //   );
    return [
        [['remote_table', 'remote_id', 'field'], 'required'],
        [['remote_id'], 'integer'],
        [['remote_table', 'field'], 'string', 'max' => 255],
        [['value'], 'string', 'strict' => false, 'max' => 255],
    ];
}

Or, the following would be more acceptable if I could edit the parent’s rules.

public function rules()
{
    return [
        [['remote_table', 'remote_id', 'field'], 'required'],
        [['remote_id'], 'integer'],
        [['remote_table', 'field' /*, 'value' */], 'string', 'max' => 255]
    ];
}

If you don’t mind, would you please tell us about the details of your design? What the schema of the underlying table is, what the parent and child models are like, what you need the child model for, … etc. Especially I don’t get the point why you have to validate 'value' field as a string.