Array to string conversion error when trying to use each validator

Hi, I been trying to develop a dynamic form that generates based on question in a database, but I been having a lot of problems with the validation of the form. I searched everywhere, but not non of the available ones seem to work. The most promising solution was using the “each” validator, but when I try using it, it gave me and “Array to string conversion” error that I wasn’t able to fix. If anyone knew what could be the problem with my code I would appreciate it.
Here is the code, it’s a little messy because I was testing a lot of things.
Model
public $file;
public $respuestaCorta = [];

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['idpregunta', 'idinscripcion', 'respuesta', "respuestaCorta"], 'required'],
            [['idpregunta', 'idinscripcion'], 'integer'],
            [['respuesta'], 'each', 'rule' => ['string', 'max' => 500, "message" => "Esta campo no debe tener mas de 500 caracteres"]],
            [['respuestaCorta'], 'each', 'rule' => ['string', 'max' => 50, "message" => "Esta campo no debe tener mas de 50 caracteres"]],
            [['file'], "file", "extensions" => ["zip", "rar", "pdf"], 'skipOnEmpty' => false, 'maxSize' => 5000000, 'tooBig' => 'El limite de archivo son de 5 mb'],
            [['idpregunta'], 'exist', 'skipOnError' => true, 'targetClass' => Pregunta::className(), 'targetAttribute' => ['idpregunta' => 'id']],
            [['idinscripcion'], 'exist', 'skipOnError' => true, 'targetClass' => Inscripcion::className(), 'targetAttribute' => ['idinscripcion' => 'idInscripcion']],
        ];
    }

    public function upload()
    {
        if ($this->validate()) {
            $this->file->saveAs("../web/eventos/formularios/archivos/" . $this->file->baseName . '.' . $this->file->extension);
            return true;
        } else {
            return false;
        }
    }

view

<div class="responder-formulario container">
<div class="pb-5">
    <div class="card-header darkish_bg text-white">
        <h3>Formulario de Pre-Inscripción</h3>
        <h5>Responda con <span class="pinkish_text">cuidado</span>, no se pueden editar las respuestas.</h5>
    </div>
</div>
<?php
$form = ActiveForm::begin([
    'id' => 'respuestas-form',
    'options' => ['class' => 'form-horizontal'],
]) ?>
<?php foreach ($preguntas as $i => $pregunta) : ?>
    <div class='card mb-5'>
       <div class='card-header darkish_bg text-white'>
       <h5>Pregunta <?= ($i + 1) ?></h5>
    </div>
    <div class='card-body'>
       <?= $pregunta->descripcion ?>
    </div>
    <div class='card-footer'>
        <?php if($pregunta->tipo == 1): ?>
            <?= $form->field($model, 'respuestaCorta')->textInput(['maxlength' => true])->label(false) ?>
        <?php endif; ?>
        <?php if($pregunta->tipo == 2): ?>
            <?= $form->field($model, 'respuesta')->textarea(['maxlength' => true])->label(false) ?>
        <?php endif; ?>
        <?php if($pregunta->tipo == 3): ?>
            <?= $form->field($model, 'file')->fileInput()->label(false) ?>
        <?php endif; ?>
    <?php if ($respuestaYaHechas[$i] == false) : ?>
       <?php $url = Url::toRoute(["respuesta/create?id=" . $pregunta->id . "&id2=" . $idInscripcion]) ?>
        <?= Html::a('Completar ' . ($i + 1), $url, [
            'class' => 'btn btn-lg responderPregunta'
        ]); ?>
    <?php else : ?>

    <?php if($pregunta->tipo == 3): ?>
        <span>Respuesta: <?= Html::encode($respuestaYaHechas[$i]->respuesta) ?></span>
    <?php else: ?>
            <span>Respuesta: <?= Html::a("Descargar", Html::encode($respuestaYaHechas[$i]->respuesta), ['class' => 'btn btn-lg btn-outline-success']) ?></span>
    <?php endif; ?>
    <?php endif; ?>
    </div>
    </div>
<?php endforeach; ?>
<?php ActiveForm::end() ?>

<br><br>

<?= Html::a('Volver Atrás', Url::toRoute("eventos/ver-evento/" . $evento->nombreCortoEvento), ['class' => 'btn btn-lg btn-outline-success']); ?>

Controller

public function actionResponderFormulario($slug) {

    $evento = $this->findModel("", $slug);
    $inscripcion = Inscripcion::find()->where(["idEvento" => $evento->idEvento, "idUsuario" => Yii::$app->user->identity->idUsuario])
        ->andWhere(["<>", "estado", 1])
        ->andWhere(["<>", "estado", 2])
        ->one();

    if ($inscripcion != null) {
        $preguntas = Pregunta::find()->where(["idEvento" => $evento->idEvento])->all();

        $respuestaYaHechas = [];
        foreach ($preguntas as $pregunta){
            $respuesta = RespuestaSearch::find()->where(["idpregunta" => $pregunta->id, "idinscripcion" => $inscripcion->idInscripcion])->one();
            if($respuesta == null){
                array_push($respuestaYaHechas, false);
            }else{
                array_push($respuestaYaHechas, $respuesta);
            }
        }
        $model = new RespuestaTest();
        return $this->render('responderFormulario',
                        ["preguntas" => $preguntas,
                            "evento" => $evento,
                            "idInscripcion" => $inscripcion->idInscripcion,
                            "respuestaYaHechas" => $respuestaYaHechas,
                            "model" => $model]);
    } else {
        return $this->goHome();
    }
}

Thank you

Ok. In your model you have 2 attributes (arrays) named $model->respuesta and $model->respuestaCorta … The “each” validator is only for arrays so this is good beginning. Then $model->validate() should work.

I am not sure if I understand your situation, but in the view you must prepare those inputs to behave like arrays and you must then use them to create the array in controller. If you check the resulting HTML code (using F12 in browser) you will see that all inputs for these attributes will probably have identical names. Which is wrong, they will overwrite each other.

So you need to specify differrent names for each of these inputs. HTML input can have following name which will allow more inputs with identical names:

<input name="Model[respuesta][0]">
<input name="Model[respuesta][1]">
<input name="Model[respuesta][2]">

… and this is what you need to reach I think. Then you will be able to loop all inputs in your controller like this:

$model->respuesta = [];
if (is_array($_GET['Model']['respuesta'])) {
  foreach ($_GET['Model']['respuesta'] as $r) {
    $model->respuesta[] = $r;
  }
}

https://www.yiiframework.com/doc/api/2.0/yii-validators-eachvalidator

https://www.yiiframework.com/doc/guide/2.0/en/helper-html#input-names-and-values

https://www.yiiframework.com/doc/guide/1.1/en/form.table

And if you ever need some smart simple piece of code or an explanation, bookmark my Yii article where I publish quick way how to implement things just by copying and pasting. It also links my previous articles about Yii1 and general Yii programming and concepts…
https://www.yiiframework.com/wiki/2552/yii-v2-snippet-guide