Array to string conversion error when saving with associations and validation errors occur

This is a (multiple allowed):

  • [x] bug

  • [ ] enhancement

  • [ ] feature-discussion (RFC)

  • CakePHP Version: 3.6.10.

  • Platform and Target: wampp server.

What you did

Good morning, I made a form that sends the next data.

[
	'crtxtipodocumento_id' => '1',
	'numerodocumento' => '111111',
	'digito_verificacion' => '1',
	'lugar_expedicion' => '123',
	'razon_social' => '111111111',
	'regimen' => 'SIMPLIFICADO',
	'telefono_principal' => '1111111111',
	'primer_nombre' => '1111111111',
	'otros_nombres' => '1111111111111',
	'apellido_paterno' => '11111111111',
	'apellido_materno' => '111111111111',
	'fecha_nacimiento' => '2018-12-03',
	'email' => '1111111',
	'email_2' => '11111111111',
	'direccion' => '111111111111',
	'direccion_correspondencia' => '11111111111111',
	'crtxdepartamento_id' => '23',
	'crtxciudade_id' => '5038',
	'representante_legal' => '111111111',
	'tipo_doc_representantelegal' => 'OTRO',
	'doc_representantelegal' => '1111111111',
	'lugar_exp_doc_representantelegal' => '111111111111',
	'crtxtelefonos' => [
		(int) 0 => [
			'name' => '1111111111',
			'tipo' => 'FIJO',
			'extension' => ''
		],
		(int) 1 => [
			'name' => '222222222222222',
			'tipo' => 'PBX',
			'extension' => '22222222222'
		]
	],
	'crtxcuentas' => [
		(int) 0 => [
			'tipo' => 'AHORROS',
			'crtxbanco_id' => '1',
			'name' => '111111111'
		]
	]
]

I am trying to save a person with phones and bank accounts information.
input example
<input type="text" name="crtxtelefonos[0][tipo]">
this inputs are generated with javascript

What happened

It saves when there are not validation errors, but that is not the problem, the problem is that when there are validations errors, it goes back to the view with the next data in the model:

object(App\Model\Entity\Crtxpersona) {

	'crtxtipodocumento_id' => (int) 1,
	'numerodocumento' => (int) 111111,
	'digito_verificacion' => (int) 1,
	'lugar_expedicion' => '123',
	'razon_social' => '111111111',
	'regimen' => 'SIMPLIFICADO',
	'telefono_principal' => (int) 1111111111,
	'primer_nombre' => '1111111111',
	'otros_nombres' => '1111111111111',
	'apellido_paterno' => '11111111111',
	'apellido_materno' => '111111111111',
	'fecha_nacimiento' => object(Cake\I18n\FrozenDate) {

		'time' => '2018-12-03T00:00:00+00:00',
		'timezone' => 'UTC',
		'fixedNowTime' => false
	
	},
	'email_2' => '11111111111',
	'direccion' => '111111111111',
	'direccion_correspondencia' => '11111111111111',
	'crtxdepartamento_id' => (int) 23,
	'crtxciudade_id' => (int) 5038,
	'representante_legal' => '111111111',
	'tipo_doc_representantelegal' => 'OTRO',
	'doc_representantelegal' => '1111111111',
	'lugar_exp_doc_representantelegal' => '111111111111',
	'crtxtelefonos' => [
		(int) 0 => object(App\Model\Entity\Crtxtelefono) {

			'name' => '1111111111',
			'tipo' => 'FIJO',
			'extension' => '',
			'createdby' => (int) 1,
			'deleted' => false,
			'created' => object(Cake\I18n\FrozenTime) {

				'time' => '2018-12-12T20:40:39+00:00',
				'timezone' => 'UTC',
				'fixedNowTime' => false
			
			},
			'[new]' => true,
			'[accessible]' => [
				'crtxpersona_id' => true,
				'name' => true,
				'tipo' => true,
				'extension' => true,
				'created' => true,
				'createdby' => true,
				'modified' => true,
				'modifiedby' => true,
				'deleted' => true,
				'crtxpersona' => true
			],
			'[dirty]' => [
				'name' => true,
				'tipo' => true,
				'extension' => true,
				'createdby' => true,
				'deleted' => true,
				'created' => true
			],
			'[original]' => [],
			'[virtual]' => [],
			'[errors]' => [],
			'[invalid]' => [],
			'[repository]' => 'Crtxtelefonos'
		
		},
		(int) 1 => object(App\Model\Entity\Crtxtelefono) {

			'name' => '222222222222222',
			'tipo' => 'PBX',
			'extension' => '22222222222',
			'createdby' => (int) 1,
			'deleted' => false,
			'created' => object(Cake\I18n\FrozenTime) {

				'time' => '2018-12-12T20:40:39+00:00',
				'timezone' => 'UTC',
				'fixedNowTime' => false
			
			},
			'[new]' => true,
			'[accessible]' => [
				'crtxpersona_id' => true,
				'name' => true,
				'tipo' => true,
				'extension' => true,
				'created' => true,
				'createdby' => true,
				'modified' => true,
				'modifiedby' => true,
				'deleted' => true,
				'crtxpersona' => true
			],
			'[dirty]' => [
				'name' => true,
				'tipo' => true,
				'extension' => true,
				'createdby' => true,
				'deleted' => true,
				'created' => true
			],
			'[original]' => [],
			'[virtual]' => [],
			'[errors]' => [],
			'[invalid]' => [],
			'[repository]' => 'Crtxtelefonos'
		
		}
	],
	'crtxcuentas' => [
		(int) 0 => object(Cake\ORM\Entity) {

			'tipo' => 'AHORROS',
			'crtxbanco_id' => (int) 1,
			'name' => '111111111',
			'createdby' => (int) 1,
			'deleted' => false,
			'created' => object(Cake\I18n\FrozenTime) {

				'time' => '2018-12-12T20:40:39+00:00',
				'timezone' => 'UTC',
				'fixedNowTime' => false
			
			},
			'[new]' => true,
			'[accessible]' => [
				'*' => true
			],
			'[dirty]' => [
				'tipo' => true,
				'crtxbanco_id' => true,
				'name' => true,
				'createdby' => true,
				'deleted' => true,
				'created' => true
			],
			'[original]' => [],
			'[virtual]' => [],
			'[errors]' => [],
			'[invalid]' => [],
			'[repository]' => 'Crtxcuentas'
		
		}
	],
	'createdby' => (int) 1,
	'deleted' => false,
	'[new]' => true,
	'[accessible]' => [
		'crtxtipodocumento_id' => true,
		'crtxdepartamento_id' => true,
		'crtxciudade_id' => true,
		'numerodocumento' => true,
		'digito_verificacion' => true,
		'apellido_paterno' => true,
		'apellido_materno' => true,
		'primer_nombre' => true,
		'otros_nombres' => true,
		'nombres_completos' => true,
		'razon_social' => true,
		'direccion' => true,
		'telefono_principal' => true,
		'email' => true,
		'email_2' => true,
		'lugar_expedicion' => true,
		'direccion_correspondencia' => true,
		'regimen' => true,
		'fecha_nacimiento' => true,
		'copropiedad' => true,
		'contratista' => true,
		'inmobiliaria' => true,
		'aseguradora' => true,
		'representante_legal' => true,
		'tipo_doc_representantelegal' => true,
		'doc_representantelegal' => true,
		'lugar_exp_doc_representantelegal' => true,
		'created' => true,
		'createdby' => true,
		'modified' => true,
		'modifiedby' => true,
		'deleted' => true,
		'crtxtipodocumento' => true,
		'crtxdepartamento' => true,
		'crtxciudade' => true,
		'crtxcontratopersonas' => true,
		'crtxcopropiedades' => true,
		'crtxcuentainmuebles' => true,
		'crtxcuentas' => true,
		'crtxpqrs' => true,
		'crtxreparacionesgenerales' => true,
		'crtxsolicitudarrendamientos' => true,
		'crtxtelefonos' => true
	],
	'[dirty]' => [
		'crtxtipodocumento_id' => true,
		'numerodocumento' => true,
		'digito_verificacion' => true,
		'lugar_expedicion' => true,
		'razon_social' => true,
		'regimen' => true,
		'telefono_principal' => true,
		'primer_nombre' => true,
		'otros_nombres' => true,
		'apellido_paterno' => true,
		'apellido_materno' => true,
		'fecha_nacimiento' => true,
		'email_2' => true,
		'direccion' => true,
		'direccion_correspondencia' => true,
		'crtxdepartamento_id' => true,
		'crtxciudade_id' => true,
		'representante_legal' => true,
		'tipo_doc_representantelegal' => true,
		'doc_representantelegal' => true,
		'lugar_exp_doc_representantelegal' => true,
		'crtxtelefonos' => true,
		'crtxcuentas' => true,
		'createdby' => true,
		'deleted' => true
	],
	'[original]' => [],
	'[virtual]' => [],
	'[errors]' => [
		'email' => [
			'email' => 'The provided value is invalid'
		]
	],
	'[invalid]' => [
		'email' => '1111111'
	],
	'[repository]' => 'Crtxpersonas'

}

As you can see the associations data is in there and when it tries to put it back in the view, it gives me the next error:

Notice (8): Array to string conversion [CORE\src\View\Helper\FormHelper.php, line 1759]
Notice (8): Array to string conversion [CORE\src\View\StringTemplate.php, line 311]

I did unset the associations data from the model, but the problem keeps happening.

How can I fix it? It does not matter if the associations data does not goes back to the view.

Thanks.

you need to give us code for your action and template without it its too vague what you are doing

function add/edit in controllers

    public function add()
        {
            $crtxpersona = $this->Crtxpersonas->newEntity();

            if ($this->request->is('post')) {
                $data = $this->request->getData();
                $associations = ['crtxpersonas', 'crtxtelefonos'];

                $crtxpersona = $this->Crtxpersonas->patchEntity($crtxpersona, $data, [
                    'associated' => $associations
                ]);
                
                if ($this->Crtxpersonas->save($crtxpersona)) {
                    
                    $this->Flash->success(__('The crtxpersona has been saved.'));

                    return $this->redirect(['action' => 'index']);
                }
                $this->Flash->error(__('The crtxpersona could not be saved. Please, try again.'));
            }
            $this->set(compact('crtxpersona'));
        }

in the form the model fields are generated with cakephp helper, but the associations fields are generated dynamically with javascript.

<?= $this->Form->create($crtxpersona) ?>
    <div class="row">
        <!-- model fields look like this -->
        <div class="col-md-3">
            <div class="form-group">
                <?php  echo $this->Form->control('crtxcuentas', ['class' => 'form-control']); ?>
            </div>
        </div>
        <!-- more model fields here -->
        <!-- asocciations fields look like this -->
        <!-- 0 -->
        <div class="col-md-3">
            <div class="form-group">
                <input type="text" name="crtxtelefonos[0][numero_cuenta]">
            </div>
        </div>
        <div class="col-md-3">
            <div class="form-group">
                <input type="text" name="crtxtelefonos[0][tipo_cuenta]">
            </div>
        </div>
        <!-- 1 -->
        <div class="col-md-3">
            <div class="form-group">
                <input type="text" name="crtxtelefonos[1][numero_cuenta]">
            </div>
        </div>
        <div class="col-md-3">
            <div class="form-group">
                <input type="text" name="crtxtelefonos[1][tipo_cuenta]">
            </div>
        </div>
    </div>
<?= $this->Form->button(__('Guardar'), ['class' => 'btn btn-success']) ?>
<?= $this->Form->end() ?>

The data send in the request is:

[
	'crtxtipodocumento_id' => '1',
	'numerodocumento' => '111111',
	'digito_verificacion' => '1',
	'lugar_expedicion' => '123',
	'razon_social' => '111111111',
	'regimen' => 'SIMPLIFICADO',
	'telefono_principal' => '1111111111',
	'primer_nombre' => '1111111111',
	'otros_nombres' => '1111111111111',
	'apellido_paterno' => '11111111111',
	'apellido_materno' => '111111111111',
	'fecha_nacimiento' => '2018-12-03',
	'email' => '1111111',
	'email_2' => '11111111111',
	'direccion' => '111111111111',
	'direccion_correspondencia' => '11111111111111',
	'crtxdepartamento_id' => '23',
	'crtxciudade_id' => '5038',
	'representante_legal' => '111111111',
	'tipo_doc_representantelegal' => 'OTRO',
	'doc_representantelegal' => '1111111111',
	'lugar_exp_doc_representantelegal' => '111111111111',
	'crtxtelefonos' => [
		(int) 0 => [
			'name' => '1111111111',
			'tipo' => 'FIJO',
			'extension' => ''
		],
		(int) 1 => [
			'name' => '222222222222222',
			'tipo' => 'PBX',
			'extension' => '22222222222'
		]
	],
	'crtxcuentas' => [
		(int) 0 => [
			'tipo' => 'AHORROS',
			'crtxbanco_id' => '1',
			'name' => '111111111'
		]
	]
]

The patchEntity() works fine and if there are no validations errors, it saves. The problem comes when there are validation errors and the model goes back to the view.
I get the next error where the associations input were before submiting the form.
Notice (8): Array to string conversion [CORE\src\View\Helper\FormHelper.php, line 1759]
Notice (8): Array to string conversion [CORE\src\View\StringTemplate.php, line 311]

its this line

<?php  echo $this->Form->control('crtxcuentas', ['class' => 'form-control']); ?>

by default cake is trying to convert what you gave it to fit ‘text’ type input and you probably modify it using JS and sending it as array of data

    'crtxcuentas' => [
		(int) 0 => [
			'tipo' => 'AHORROS',
			'crtxbanco_id' => '1',
			'name' => '111111111'
		]
	]

you can modify it so you give it value you know your JS needs as string like:

<?= $this->Form->control('crtxcuentas', [
   'class' => 'form-control',
   'value' => $crtxpersona->crtxcuentas ? array_reduce($crtxpersona->crtxcuentas, function($acc, $item) { return $acc . ',' . $item['crtxbanco_id']; }, '') : ''
]) ?>

Thank you!
It was my mistake, I was creating a field with the name of the associated table, so cakephp was trying to put the array value there. (the field has permissions purposes).