Can't save associated model

I have two tables associated with belongsTomany (Teams and Professionals, join table ProfessionalsTeams) when I try to save them in TeamsController I debug($team) and shows me this:

APP/Controller\TeamsController.php (line 66)
object(App\Model\Entity\Team) id:0 {
  'pacient_id' => (int) 28
  'professionals' => [
  ]
  'date' => object(Cake\I18n\FrozenDate) id:1 {
    'time' => '2023-11-21 00:00:00.000000-03:00'
    'timezone' => 'America/Argentina/Cordoba'
    'fixedNowTime' => false
  }
  'observations' => 'Prueba de profesionales'
  'anulled' => false
  '_joinData' => object(Cake\ORM\Entity) id:2 {
    'profile_id' => '2'
    'generate' => '1'
    '[new]' => true
    '[accessible]' => [
      '*' => true,
    ]
    '[dirty]' => [
      'profile_id' => true,
      'generate' => true,
    ]
    '[original]' => [
    ]
    '[virtual]' => [
    ]
    '[hasErrors]' => false
    '[errors]' => [
    ]
    '[invalid]' => [
    ]
    '[repository]' => ''
  }
  '[new]' => true
  '[accessible]' => [
    'pacient_id' => true,
    'date' => true,
    'observations' => true,
    'created' => true,
    'modified' => true,
    'anulled' => true,
    'pacient' => true,
    'professionals' => true,
  ]
  '[dirty]' => [
    'pacient_id' => true,
    'professionals' => true,
    'date' => true,
    'observations' => true,
    'anulled' => true,
    '_joinData' => true,
  ]
  '[original]' => [
  ]
  '[virtual]' => [
  ]
  '[hasErrors]' => false
  '[errors]' => [
  ]
  '[invalid]' => [
  ]
  '[repository]' => 'Teams'
}

This is the code for add action:

    public function add()
    {
        $team = $this->Teams->newEmptyEntity();
        if ($this->request->is('post')) {
            $team = $this->Teams->newEntity($this->request->getData(), ['associated' => 'Professionals']);
			$profile_id = $this->request->getData('professionals.0._joinData.profile_id');
			$generate = $this->request->getData('professionals.0._joinData.generate');
			$joinData = new Entity(['profile_id' => $profile_id, 'generate' => $generate], ['markNew' => true]);
            $team->_joinData = $joinData;
			if ($this->Teams->save($team)) {
                $this->Flash->success(__('El equipo ha sido guardado.'));

                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('El equipo no pudo ser guardado. Por favor, intente nuevamente.'));
        }
        $pacients = $this->Teams->Pacients->find('list', ['limit' => 200])->all();
        $professionals = $this->Teams->Professionals->find('list', ['limit' => 200])->all();
        $this->set(compact('team', 'pacients', 'professionals'));
    }

And this is the code for add template:

<?php
/**
 * @var \App\View\AppView $this
 * @var \App\Model\Entity\Team $team
 * @var \Cake\Collection\CollectionInterface|string[] $pacients
 * @var \Cake\Collection\CollectionInterface|string[] $professionals
 */
?>
<div class="row">
    <?php 
		$this->Breadcrumbs->add([
			['title' => 'Inicio', 'url' => ['controller' => 'Home', 'action' => 'index'], 'options' => ['class' => 'breadcrumb-item']],
			['title' => 'Equipos', 'url' => ['action' => 'index'], 'options' => ['class' => 'breadcrumb-item']],
			['title' => 'Agregar Equipo', 'options' => ['class' => 'breadcrumb-item']],
		]);
	?>
	<?= $this->Breadcrumbs->render(['class' => 'breadcrumb']) ?>
    <div class="column-responsive column-80">
        <div class="teams form content">
            <?= $this->Form->create($team) ?>
            <fieldset>
                <legend><?= __('Agregar Equipo') ?></legend>
                <?php
                    echo $this->Form->control('pacient_id', ['label' => 'Paciente', 'options' => $pacients, 'empty' => '- Seleccione un paciente -', 'id' => 'pacient']);
                    echo $this->Html->tag('div', '', ['class'=>'tagPaciente', 'style'=>'display:none', 'id'=>'showPacient']);
                    echo $this->Form->control('professionals._ids', ['label' => 'Coordinador', 'options' => $professionals, 'empty' => '- Seleccione un profesional -', 'multiple' => false, 'id' => 'professional']);
                    echo $this->Form->hidden('professionals.0._joinData.profile_id', ['value' => 2]);
                    echo $this->Form->hidden('professionals.0._joinData.generate', ['value' => 1]);
                    echo $this->Html->tag('div', '', ['class'=>'tagProfesional', 'style'=>'display:none', 'id'=>'showProfessional']);
                    echo $this->Form->control('date', ['label' => 'Fecha', 'value' => date('Y-m-d'), 'class' => 'input-date']);
                    echo $this->Form->control('observations', ['label' => 'Observaciones']);
                    echo $this->Form->hidden('anulled', ['value' => 0]);
                ?>
            </fieldset>
            <?= $this->Form->button(__('Guardar')) ?>
            <?= $this->Form->end() ?>
        </div>
    </div>
</div>
<script>
$(function(){
	$('#pacient').change(function(){
		$.ajax({
			method:"POST",
			url:"<?= $this->Url->build(['controller' => 'Pacients', 'action' => 'showPacient']) ?>",
			data:{
				pacient_id:$(this).val()
			},
			success:function(data) {
				$('#showPacient').html(data);
				$('.tagPaciente').show();
			},
			headers:{
				'X-CSRF-Token':$('meta[name="csrfToken"]').attr('content')
			}
		});
	});
})
$(function(){
	$('#professional').change(function(){
		$.ajax({
			method:"POST",
			url:"<?= $this->Url->build(['controller' => 'Professionals', 'action' => 'showProfessional']) ?>",
			data:{
				professional_id:$(this).val()
			},
			success:function(data) {
				$('#showProfessional').html(data);
				$('.tagProfesional').show();
			},
			headers:{
				'X-CSRF-Token':$('meta[name="csrfToken"]').attr('content')
			}
		});
	});
})
</script>

How can I solve this issue?

What’s the issue? You’ve shown us what it looks like, but not told us what the problem is with it.

Sorry, the problem is that the newentity method doesn’t create the professionals entity and doesn’t save the record for ProfessionalsTeams table

I suspect that mixing professionals._ids and professionals.0._joinData in your form may be causing the problem. Given that the join data appears to have fixed values, can you not set those directly in your post handling code in the controller instead of in the form?

Is still not creating the professionals entity, this is what it shows debug($team):

APP/Controller\TeamsController.php (line 67)
object(App\Model\Entity\Team) id:0 {
  'pacient_id' => (int) 28
  'professionals' => [
  ]
  'date' => object(Cake\I18n\FrozenDate) id:1 {
    'time' => '2023-11-23 00:00:00.000000-03:00'
    'timezone' => 'America/Argentina/Cordoba'
    'fixedNowTime' => false
  }
  'observations' => 'Prueba de profesionales'
  '_joinData' => object(Cake\ORM\Entity) id:2 {
    'profile_id' => (int) 2
    'generate' => (int) 1
    '[new]' => true
    '[accessible]' => [
      '*' => true,
    ]
    '[dirty]' => [
      'profile_id' => true,
      'generate' => true,
    ]
    '[original]' => [
    ]
    '[virtual]' => [
    ]
    '[hasErrors]' => false
    '[errors]' => [
    ]
    '[invalid]' => [
    ]
    '[repository]' => ''
  }
  'anulled' => (int) 0
  '[new]' => true
  '[accessible]' => [
    'pacient_id' => true,
    'date' => true,
    'observations' => true,
    'created' => true,
    'modified' => true,
    'anulled' => true,
    'pacient' => true,
    'log_teams' => true,
    'professionals_teams' => true,
    'log_professionals' => true,
    'professionals' => true,
  ]
  '[dirty]' => [
    'pacient_id' => true,
    'professionals' => true,
    'date' => true,
    'observations' => true,
    '_joinData' => true,
    'anulled' => true,
  ]
  '[original]' => [
  ]
  '[virtual]' => [
  ]
  '[hasErrors]' => false
  '[errors]' => [
  ]
  '[invalid]' => [
  ]
  '[repository]' => 'Teams'
}

This is the code for add action:

    public function add()
    {
        $team = $this->Teams->newEmptyEntity();
        if ($this->request->is('post')) {
            $team = $this->Teams->patchEntity($team, $this->request->getData(), ['associated' => 'Professionals']);
			$profile_id = 2;
			$generate = 1;
			$joinData = new Entity(['profile_id' => $profile_id, 'generate' => $generate], ['markNew' => true]);
            $team->_joinData = $joinData;
			$team->anulled = 0;
			debug($team);
			if ($this->Teams->save($team)) {
                $this->Flash->success(__('El equipo ha sido guardado.'));

                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('El equipo no pudo ser guardado. Por favor, intente nuevamente.'));
        }
        $pacients = $this->Teams->Pacients->find('list', ['limit' => 200])->all();
        $professionals = $this->Teams->Professionals->find('list', ['limit' => 200])->all();
        $this->set(compact('team', 'pacients', 'professionals'));
    }

And this is the code for add template:

<?php
/**
 * @var \App\View\AppView $this
 * @var \App\Model\Entity\Team $team
 * @var \Cake\Collection\CollectionInterface|string[] $pacients
 * @var \Cake\Collection\CollectionInterface|string[] $professionals
 */
?>
<div class="row">
    <?php 
		$this->Breadcrumbs->add([
			['title' => 'Inicio', 'url' => ['controller' => 'Home', 'action' => 'index'], 'options' => ['class' => 'breadcrumb-item']],
			['title' => 'Equipos', 'url' => ['action' => 'index'], 'options' => ['class' => 'breadcrumb-item']],
			['title' => 'Agregar Equipo', 'options' => ['class' => 'breadcrumb-item']],
		]);
	?>
	<?= $this->Breadcrumbs->render(['class' => 'breadcrumb']) ?>
    <div class="column-responsive column-80">
        <div class="teams form content">
            <?= $this->Form->create($team) ?>
            <fieldset>
                <legend><?= __('Agregar Equipo') ?></legend>
                <?php
                    echo $this->Form->control('pacient_id', ['label' => 'Paciente', 'options' => $pacients, 'empty' => '- Seleccione un paciente -', 'id' => 'pacient']);
                    echo $this->Html->tag('div', '', ['class'=>'tagPaciente', 'style'=>'display:none', 'id'=>'showPacient']);
                    echo $this->Form->control('professionals._ids', ['label' => 'Coordinador', 'options' => $professionals, 'empty' => '- Seleccione un profesional -', 'multiple' => false, 'id' => 'professional']);
                    echo $this->Html->tag('div', '', ['class'=>'tagProfesional', 'style'=>'display:none', 'id'=>'showProfessional']);
                    echo $this->Form->control('date', ['label' => 'Fecha', 'value' => date('Y-m-d'), 'class' => 'input-date']);
                    echo $this->Form->control('observations', ['label' => 'Observaciones']);
                ?>
            </fieldset>
            <?= $this->Form->button(__('Guardar')) ?>
            <?= $this->Form->end() ?>
        </div>
    </div>
</div>
<script>
$(function(){
	$('#pacient').change(function(){
		$.ajax({
			method:"POST",
			url:"<?= $this->Url->build(['controller' => 'Pacients', 'action' => 'showPacient']) ?>",
			data:{
				pacient_id:$(this).val()
			},
			success:function(data) {
				$('#showPacient').html(data);
				$('.tagPaciente').show();
			},
			headers:{
				'X-CSRF-Token':$('meta[name="csrfToken"]').attr('content')
			}
		});
	});
})
$(function(){
	$('#professional').change(function(){
		$.ajax({
			method:"POST",
			url:"<?= $this->Url->build(['controller' => 'Professionals', 'action' => 'showProfessional']) ?>",
			data:{
				professional_id:$(this).val()
			},
			success:function(data) {
				$('#showProfessional').html(data);
				$('.tagProfesional').show();
			},
			headers:{
				'X-CSRF-Token':$('meta[name="csrfToken"]').attr('content')
			}
		});
	});
})
</script>

How can I solve this issue?

Is professionals._ids an array in the submitted data, or just an integer? You’re looking to just link to one pre-existing professional? Maybe you should be using _joinData.professional_id instead of _ids? Sorry, I don’t have time to give a comprehensive answer right now, just throwing out some ideas to look at.

Maybe that’s the solución because I want to add only one existing professional

See also the link function. Set the _joinData in the entity you are linking. In their example, $articlesTable->Tags->link($article, [$tag1, $tag2]);, you’d set it on $tag1 and $tag2, not $article.

I did as you suggested but when I try to save the entities using $team = $this->Teams->newEntity($this->request->getData(), ['associated' => 'Professionals']); gives me these errors (pr($team->getErrors())):

Array
(
    [professionals] => Array
        (
            [0] => Array
                (
                    [last_name] => Array
                        (
                            [_required] => This field is required
                        )

                    [name] => Array
                        (
                            [_required] => This field is required
                        )

                    [document_type] => Array
                        (
                            [_required] => This field is required
                        )

                    [document_number] => Array
                        (
                            [_required] => This field is required
                        )

                    [birthday] => Array
                        (
                            [_required] => This field is required
                        )

                    [sex] => Array
                        (
                            [_required] => This field is required
                        )

                    [image_file_name] => Array
                        (
                            [_required] => This field is required
                        )

                    [selected] => Array
                        (
                            [_required] => This field is required
                        )

                    [anulled] => Array
                        (
                            [_required] => This field is required
                        )

                )

        )

)

In these errors are involved the fields of professionals table.
And when I use $team = $this->Teams->newEntity($this->request->getData(), ['associated' => ['Professionals' => ['onlyIds' => true]]]); it gives me this exception:


This is the code for add action:

    public function add()
    {
        $team = $this->Teams->newEmptyEntity();
        if ($this->request->is('post')) {
            $team = $this->Teams->newEntity($this->request->getData(), ['associated' => ['Professionals' => ['onlyIds' => true]]]);
			$professional_id = $this->request->getData('professionals.0._joinData.professional_id');
			$profile_id = 2;
			$generate = 1;
			$joinData = new Entity(['professional_id' => $professional_id, 'profile_id' => $profile_id, 'generate' => $generate, 'anulled' => 0], ['markNew' => true]);
            $team->professionals[0]->_joinData = $joinData;
			$team->anulled = 0;
			// debug($team);
			if ($this->Teams->save($team)) {
                $this->Flash->success(__('El equipo ha sido guardado.'));

                return $this->redirect(['action' => 'index']);
            }
            pr($team->getErrors());
			// $this->Flash->error(__('El equipo no pudo ser guardado. Por favor, intente nuevamente.'));
        }
        $pacients = $this->Teams->Pacients->find('list', ['limit' => 200])->all();
        $professionals = $this->Teams->Professionals->find('list', ['limit' => 200])->all();
        $this->set(compact('team', 'pacients', 'professionals'));
    }

How can I avoid the addition of a new record in professionals table?

You could use link, as I suggested in my previous comment.

Thank you @Zuluru, now it works perfect