Set index for belongstomany join table in index view

I have two tables with a belongstomany association (Groups and Users, join table GroupsUsers) I created a hasmany association between Groups and GroupsUsers to retrieve its data in index view of Users controller, this is the code for index view:

<?php
/**
 * @var \App\View\AppView $this
 * @var iterable<\App\Model\Entity\User> $users
 */
?>
<div class="users index content">
    <?php
		if(!empty($checkUA1) || !empty($checkUA2)) echo $this->Html->link(__('Agregar usuario'), ['action' => 'add'], ['class' => 'button float-right']);
		echo $this->Form->create(null, ['valueSources' => 'query']);
		echo $this->Form->control('search', ['label' => 'Buscar', 'placeholder' => 'Buscar por nombre de usuario o e-mail']);
		echo $this->Form->button(__('Buscar'), ['class' => 'btn btn-primary']);
		if (!empty($_isSearch)) {
			echo ' ';
			echo $this->Html->link(__('Reset'), ['action' => 'index', '?' => array_intersect_key($this->request->getQuery(), array_flip(['sort', 'direction']))], ['class' => 'btn btn-default']);
		}
		echo $this->Form->end();
	?>
    <h3><?= __('Usuarios') ?></h3>
    <div class="table-responsive">
        <table>
            <thead>
                <tr>
                    <th><?= $this->Paginator->sort('image_file_name_url', 'Foto de perfil') ?></th>
                    <th><?= $this->Paginator->sort('username', 'Nombre de usuario') ?></th>
                    <th><?= $this->Paginator->sort('email', 'E-mail') ?></th>
                    <th><?= $this->Paginator->sort('firstname', 'Nombre') ?></th>
                    <th><?= $this->Paginator->sort('lastname', 'Apellido') ?></th>
                    <th><?= $this->Paginator->sort('created', 'Creado') ?></th>
                    <th><?= $this->Paginator->sort('modified', 'Modificado') ?></th>
                    <th><?= $this->Paginator->sort('profile_id', 'Perfil') ?></th>
                    <th><?= $this->Paginator->sort('group_id', 'Célula') ?></th>
                    <th><?= $this->Paginator->sort('net_id', 'Unidad funcional') ?></th>
                    <th><?= $this->Paginator->sort('main_gate', 'Nodo') ?></th>
                    <th><?= $this->Paginator->sort('referrer_id', 'Referente') ?></th>
                    <th><?= $this->Paginator->sort('active', 'Activo') ?></th>
                    <th><?= $this->Paginator->sort('map_lat', 'Latitud') ?></th>
                    <th><?= $this->Paginator->sort('map_long', 'Longitud') ?></th>
                    <th><?= $this->Paginator->sort('Estado') ?></th>
                    <th><?= $this->Paginator->sort('Aislado') ?></th>
                    <th class="actions"><?= __('Acciones') ?></th>
                </tr>
            </thead>
            <tbody>
                <?php
					foreach ($users as $user):
						$color = '';
						switch ($user->profile_id) {
							case '1':
								$color = '#000000';
								break;
							case '2':
								$color = '#041d54';
								break;
							case '3':
								$color = '#540404';
								break;
							case '4':
								$color = '#6D147A';
								break;
							case '5':
								$color = '#CC7400';
								break;
							case '6':
								$color = '#2E2EBF';
								break;            
							default:
								$color = '#30773D';
								break;
						}
						$colorAlert = '';
						switch($user->status){
							case 1: $colorAlert = '#18FE00';
								break;
							case 2: $colorAlert = '#FFFF00';
								break;
							case 3: $colorAlert = '#FF8000';
								break;
							case 4: $colorAlert = '#FF0000';
								break;
							default: $colorAlert = '#FFFFFF';
								break;
						}
						$group = "";
						$net = "";
						$gate = "";
						if($user->has("groups")):
							foreach ($user->groups as $groups):
								$key = $groups->_joinData->user_id - 4;
								debug($groups);
								$mostrarGroup = (!empty($checkGV1) || !empty($checkGV2) || !empty($checkGV3) || !empty($checkGV4) || !empty($checkGV5)) ? 
									$this->Html->link($groups->group_name, ['controller' => 'Groups', 'action' => 'view', $groups->id]) : h($groups->group_name);
								$group .= $this->Html->tag("p", $mostrarGroup);
								if(!empty($groups->_joinData->net_id)){
									$net = (!empty($checkNV1) || !empty($checkNV2) || !empty($checkNV3) || !empty($checkNV4) || !empty($checkNV5)) ? 
										$this->Html->link($groups->groups_users[$key]->net->net_name, ['controller' => 'Nets', 'action' => 'view', 
										$groups->_joinData->net_id]) : h($groups->groups_users[$key]->net->net_name);
								}
								$gate = $groups->_joinData->main_gate;
							endforeach;
						endif;
				?>
                <tr>
                    <td><?= $user->image_file_name_url === null ? '' : $this->Html->image($user->image_file_name_url, ['class' => 'img-circle']) ?></td>
                    <td><?= h($user->username) ?></td>
                    <td><?= h($user->email) ?></td>
                    <td><?= h($user->firstname) ?></td>
                    <td><?= h($user->lastname) ?></td>
                    <td><?= h($user->created) ?></td>
                    <td><?= h($user->modified) ?></td>
                    <td style="background-color:<?= $color ?>;color:#fff"><?= $user->has('profile') ? !empty($checkPrV1) || !empty($checkPrV2) || 
						!empty($checkPrV3) || !empty($checkPrV4) || !empty($checkPrV5) ? $this->Html->link($user->profile->name, ['controller' => 'Profiles', 
						'action' => 'view', $user->profile->id]) : h($user->profile->name) : '' ?></td>
					<td><?= (!empty($group)) ? $group : '' ?></td>
                    <td><?= (!empty($net)) ? $net : '' ?></td>
                    <td><?= (!empty($gate)) ? h($gate) : '' ?></td>
                    <td><?= $user->has('referrer') ? !empty($checkUV1) || !empty($checkUV2) || !empty($checkUV3) || !empty($checkUV4) || !empty($checkUV5) ?
							$this->Html->link($user->referrer->full_name, ['controller' => 'Users', 'action' => 'view', $user->referrer->id]) :
							h($user->referrer->full_name) : '' ?></td>
                    <td><?= h($user->active) ?></td>
                    <td><?= $user->map_lat === null ? '' : $this->Number->format($user->map_lat) ?></td>
                    <td><?= $user->map_long === null ? '' : $this->Number->format($user->map_long) ?></td>
                    <td style="background-color:<?= $colorAlert ?>;"><?php echo $statusAlertEnum[$user->status]; ?></td> 
                    <td><?= $user->isolated === null ? '' : $this->Number->format($user->isolated) ?></td>
                    <td class="actions">
                        <?= !empty($checkUC1) || !empty($checkUC2) ? $this->Html->link($this->Html->tag("span", "", ['class'=>'glyphicon glyphicon-user']), 
								['action' => 'changepassword', $user->id], ['escape' => false, 'title' => 'Cambiar contraseña']) : '' ?>
						<?= !empty($checkUS1) || !empty($checkUS2) ? $this->Html->link($this->Html->tag("span", "", ['class'=>'glyphicon glyphicon-globe']), 
								['action' => 'setgeo', $user->id], ['escape' => false, 'title' => 'Setear geolocalización']) : '' ?>
                        <?= !empty($checkUV1) || !empty($checkUV2) || !empty($checkUV3) || !empty($checkUV4) || !empty($checkUV5) ?
								$this->Html->link($this->Html->tag("span", "", ['class'=>'glyphicon glyphicon-search']), ['action' => 'view', $user->id], 
								['escape' => false, 'title' => 'Ver']) : '' ?>
                        <?= !empty($checkUE1) || !empty($checkUE2) ? $this->Html->link($this->Html->tag("span", "", ['class'=>'glyphicon glyphicon-edit']), 
								['action' => 'edit', $user->id], ['escape' => false, 'title' => 'Editar']) : '' ?>
                        <?= !empty($checkUD1) || !empty($checkUD2) ? $this->Form->postLink($this->Html->tag("span", "", ['class'=>'glyphicon glyphicon-remove']), 
								['action' => 'delete', $user->id], ['confirm' => __('Está seguro que desea eliminar a {0}?', $user->full_name), 'escape' => false, 
								'title' => 'Eliminar']) : '' ?>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
    <div class="paginator">
        <ul class="pagination">
            <?= $this->Paginator->first('<< ' . __('Primera')) ?>
            <?= $this->Paginator->prev('< ' . __('Anterior')) ?>
            <?= $this->Paginator->numbers() ?>
            <?= $this->Paginator->next(__('Siguiente') . ' >') ?>
            <?= $this->Paginator->last(__('Última') . ' >>') ?>
        </ul>
        <p><?= $this->Paginator->counter(__('Página {{page}} de {{pages}}, mostrando {{current}} registro(s) de {{count}}')) ?></p>
    </div>
</div>

The Users table has 17 records, what means that has 17 autonumeric ids and the GroupsUsers has 15 user_id, from user_id 3 to 17, Users ids 1 and 2 don’t have matching records in GroupsUsers, how can I do to set the index for GroupsUsers without using the _joinData->user_id?

There’s a lot of code here, most of which appears to have nothing to do with the question. What exactly are you trying to accomplish?

In this case the index for belongstomany join table is the $key variable, where it says $key = $groups->_joinData->user_id - 4;
I can’t send the debug($groups) because is longer than 32000 characters, but if you see the $groups has an array of 14 objects of groups_users, how can I set the key of the groups_users array to show the nets belongsto with groups_users? Now I am doing it like this: $groups->groups_users[$key]->net->net_name

Why would you need to do any of that messing around with keys? Just contain Nets in the GroupsUsers when you read the data? (You also haven’t shown us your code for reading the data…)

This is the code for index action:

    public function index()
    {
        $this->paginate = ['contain' => ['Profiles', 'Referrer', 'Groups' => ['GroupsUsers' => 'Nets']]];
		$users = [];
        if ($this->controllerUser['isAdmin']){
			$users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])->leftJoinWith('Groups')
				->where(['Users.profile_id IN' => [1,2,3,4,5,6,7]]));
		} elseif($this->controllerUser['isGeneralCoordinator']){
			$users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])->leftJoinWith('Groups')
				->where(['Users.profile_id IN' => [2,3,4,5,6,7]]));
		} elseif ($this->controllerUser['isGroupCoordinator']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])->leftJoinWith('Groups')
				->where(['Users.profile_id IN' => [3,4,5,6,7], 'Groups.id in' => $this->controllerUser['group_id']]));
        } elseif ($this->controllerUser['isNetCoordinator']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])->leftJoinWith('Groups')
				->where(['Users.profile_id IN' => [4,5,6,7], 'Groups.id' => $this->controllerUser['group_id'], 
				'GroupsUsers.net_id' => $this->controllerUser['net_id']]));
        } elseif ($this->controllerUser['isNodeCoordinator']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])->leftJoinWith('Groups')
				->where(['Users.profile_id IN' => [4,5,6,7], 'Groups.id' => $this->controllerUser['group_id'], 
				'GroupsUsers.net_id' => $this->controllerUser['net_id'], 
                'GroupsUsers.main_gate' => $this->controllerUser['main_gate']]));
        } elseif ($this->controllerUser['isTacticOperator']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])->leftJoinWith('Groups')
				->where(['Users.profile_id IN' => [4,5,6,7], 'Groups.id' => $this->controllerUser['group_id'], 
				'GroupsUsers.net_id' => $this->controllerUser['net_id'], 
                'GroupsUsers.main_gate' => $this->controllerUser['main_gate']]));
        } elseif ($this->controllerUser['isSanitaryAgent']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])->leftJoinWith('Groups')
				->where(['Users.profile_id IN' => [4,5,6,7], 'Groups.id' => $this->controllerUser['group_id'], 
				'GroupsUsers.net_id' => $this->controllerUser['net_id'], 
                'GroupsUsers.main_gate' => $this->controllerUser['main_gate']]));
        }
        $this->set(compact('users'));
		$this->set('_serialize', ['users']);
    }

How can I do to retrieve one GroupsUsers entity at a time without using foreach($groups->groups_users as $groups_users)

So, you’re getting all users, and for each user the group they are in, and for each group the list of all users in that group, and the net for each of those join records?

Why not get all users, and for each user the record from the join table, and for each of those both the group and the net? Like ['contain' => ['Profiles', 'Referrer', 'GroupsUsers' => ['Groups', 'Nets']]]

You might need to set up additional associations that you don’t have already to make this work, but it seems like the more natural data combination.

It worked fine, but it doesn’t show the belongstomany association between Users and Groups, the user_id 3 has two groups (group_id 1 and 2), how can I do to retrieve both group_id with same user_id in GroupsUsers table?

As you foreach ($users as $user) to iterate your query results, $user->groups_users (or some similarly named property) should be an array of the join records, each of which will have both a ->group and a ->net.

Yes, that’s right, but how do I have to define the association between Users and GroupsUsers so that it shows all the matching records between these two tables?
This is what it shows debug($user) in user id 3:

ROOT/templates/Users/index.php (line 87)
object(App\Model\Entity\User) id:0 {
  'id' => (int) 3
  'username' => 'cayojcs@gmail.com'
  'password' => '$2y$10$73p1Tioo9uc3y8bS5mRP8eaNyH0PGS5qmbBHcGK3ITZZlMjANwska'
  'email' => 'cayojcs@gmail.com'
  'firstname' => 'Julio Cesar'
  'lastname' => 'Sarmiento'
  'created' => object(Cake\I18n\FrozenTime) id:1 {
    'time' => '2023-03-23 13:14:49.000000-03:00'
    'timezone' => 'America/Argentina/Cordoba'
    'fixedNowTime' => false
  }
  'modified' => object(Cake\I18n\FrozenTime) id:2 {
    'time' => '2023-04-02 01:15:07.000000-03:00'
    'timezone' => 'America/Argentina/Cordoba'
    'fixedNowTime' => false
  }
  'profile_id' => (int) 3
  'referrer_id' => (int) 2
  'active' => true
  'image_file_name_url' => 'https://www.estadoatulado.com.ar/upload/Users/c2c11db8_c9cd_44fd_9c6a_556f2bd7028f_original.jpg'
  'image_file_name' => '/home/o12mg0png743/public_html/estadoatulado.com.ar/webroot/upload/Users/c2c11db8_c9cd_44fd_9c6a_556f2bd7028f_original.jpg'
  'image_file_name_filename' => 'c2c11db8_c9cd_44fd_9c6a_556f2bd7028f_original.jpg'
  'map_lat' => null
  'map_long' => null
  'code' => '1234567890'
  'status' => (int) 0
  'isolated' => false
  'token' => null
  'groups_users' => [
  ]
  'referrer' => object(App\Model\Entity\User) id:3 {
    'id' => (int) 2
    'username' => 'mdeanquin2007@hotmail.com'
    'password' => '$2y$10$ojbSkPmOhj1ptk2ZpyYfsOczTC5sdi/izYYWPAijXjRXP5z0AL0ZK'
    'email' => 'mdeanquin2007@hotmail.com'
    'firstname' => 'Juan Manuel'
    'lastname' => 'Díaz'
    'created' => object(Cake\I18n\FrozenTime) id:4 {
      'time' => '2023-03-23 12:53:51.000000-03:00'
      'timezone' => 'America/Argentina/Cordoba'
      'fixedNowTime' => false
    }
    'modified' => object(Cake\I18n\FrozenTime) id:5 {
      'time' => '2023-03-29 13:56:38.000000-03:00'
      'timezone' => 'America/Argentina/Cordoba'
      'fixedNowTime' => false
    }
    'profile_id' => (int) 2
    'referrer_id' => null
    'active' => true
    'image_file_name_url' => 'https://www.estadoatulado.com.ar/upload/Users/juan_original.jpg'
    'image_file_name' => '/home/o12mg0png743/public_html/estadoatulado.com.ar/webroot/upload/Users/juan_original.jpg'
    'image_file_name_filename' => 'juan_original.jpg'
    'map_lat' => null
    'map_long' => null
    'code' => '1234567890'
    'status' => (int) 0
    'isolated' => false
    'token' => null
    '[new]' => false
    '[accessible]' => [
      'username' => true,
      'password' => true,
      'email' => true,
      'firstname' => true,
      'lastname' => true,
      'full_name' => true,
      'created' => true,
      'modified' => true,
      'profile_id' => true,
      'referrer_id' => true,
      'active' => true,
      'image_file_name_url' => true,
      'image_file_name' => true,
      'image_file_name_filename' => true,
      'map_lat' => true,
      'map_long' => true,
      'code' => true,
      'status' => true,
      'isolated' => true,
      'token' => true,
      'aro' => true,
      'profile' => true,
      'referrer' => true,
      'statesx_days' => true,
      'doctors' => true,
      'events_users' => true,
      'observations' => true,
      'pacients' => true,
      'status_groups' => true,
      'stocks_users' => true,
      'turns' => true,
      'doctorT' => true,
      'groups' => true,
    ]
    '[dirty]' => [
    ]
    '[original]' => [
    ]
    '[virtual]' => [
    ]
    '[hasErrors]' => false
    '[errors]' => [
    ]
    '[invalid]' => [
    ]
    '[repository]' => 'Referrer'
  }
  'profile' => object(App\Model\Entity\Profile) id:6 {
    'id' => (int) 3
    'name' => 'Médico coordinador de célula'
    'description' => 'Coordinación de la célula del centro de salud'
    'referrer_profile_id' => (int) 2
    'created' => object(Cake\I18n\FrozenTime) id:7 {
      'time' => '2023-03-14 12:54:59.000000-03:00'
      'timezone' => 'America/Argentina/Cordoba'
      'fixedNowTime' => false
    }
    'modified' => object(Cake\I18n\FrozenTime) id:8 {
      'time' => '2023-03-14 12:54:59.000000-03:00'
      'timezone' => 'America/Argentina/Cordoba'
      'fixedNowTime' => false
    }
    '[new]' => false
    '[accessible]' => [
      'name' => true,
      'description' => true,
      'referrer_profile_id' => true,
      'created' => true,
      'modified' => true,
      'aro' => true,
      'referrer_profile' => true,
      'profiles_gates' => true,
      'users' => true,
      'sourcing_events' => true,
    ]
    '[dirty]' => [
    ]
    '[original]' => [
    ]
    '[virtual]' => [
    ]
    '[hasErrors]' => false
    '[errors]' => [
    ]
    '[invalid]' => [
    ]
    '[repository]' => 'Profiles'
  }
  '[new]' => false
  '[accessible]' => [
    'username' => true,
    'password' => true,
    'email' => true,
    'firstname' => true,
    'lastname' => true,
    'full_name' => true,
    'created' => true,
    'modified' => true,
    'profile_id' => true,
    'referrer_id' => true,
    'active' => true,
    'image_file_name_url' => true,
    'image_file_name' => true,
    'image_file_name_filename' => true,
    'map_lat' => true,
    'map_long' => true,
    'code' => true,
    'status' => true,
    'isolated' => true,
    'token' => true,
    'aro' => true,
    'profile' => true,
    'referrer' => true,
    'statesx_days' => true,
    'doctors' => true,
    'events_users' => true,
    'observations' => true,
    'pacients' => true,
    'status_groups' => true,
    'stocks_users' => true,
    'turns' => true,
    'doctorT' => true,
    'groups' => true,
  ]
  '[dirty]' => [
  ]
  '[original]' => [
  ]
  '[virtual]' => [
  ]
  '[hasErrors]' => false
  '[errors]' => [
  ]
  '[invalid]' => [
  ]
  '[repository]' => 'Users'
}

As you can see groups_users is empty and this user has 2 group ids associated: 1 and 2

Hard to say what you’ve done wrong in your association definition, when you’re not showing us your association definition.

like i said in your last post you need an extra hasMany relation to access your data like that. The belongsToMany only relates Users to Groups and not directly the joinTable

I have a hasMany association between Users and GroupsUsers, is defined this way in UsersTable.php:

        $this->hasMany('GroupsUsers', [
            'foreignKey' => 'user_id',
        ]);

What am I doing wrong?

You are adding bringing the Groups associations not the GroupsUsers association.
As Zuluru mentioned, you should get the associations this way in order to work:

['contain' => ['Profiles', 'Referrer', 'GroupsUsers' => ['Groups', 'Nets']]]

Does the Groups table have a GroupsUsers relation?

I created a hasMany relation between Groups and GroupsUsers in GroupsTable.php like this:

$this->hasMany('GroupsUsers', [
      'foreignKey' => 'group_id',
]);

But it still doesn’t show the belongstomany associations between Groups and Users, what am I doing wrong?

Have you updated the containment in your pagination?

Yes, this is the code for index action:

    public function index()
    {
        $this->paginate = ['contain' => ['Profiles', 'Referrer', 'GroupsUsers' => ['Groups', 'Nets']]];
		$users = [];
        if ($this->controllerUser['isAdmin']){
			$query = $this->Users->find('all')->contain(['Profiles','Referrer', 'GroupsUsers' => ['Groups', 'Nets']])->where(['Users.profile_id IN' => [1,2,3,4,5,6,7]]);
			sql($query);
			$users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])
				->where(['Users.profile_id IN' => [1,2,3,4,5,6,7]]));
		} elseif($this->controllerUser['isGeneralCoordinator']){
			$users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])
				->where(['Users.profile_id IN' => [2,3,4,5,6,7]]));
		} elseif ($this->controllerUser['isGroupCoordinator']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])
				->where(['Users.profile_id IN' => [3,4,5,6,7], 'Groups.id in' => $this->controllerUser['group_id']]));
        } elseif ($this->controllerUser['isNetCoordinator']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])
				->where(['Users.profile_id IN' => [4,5,6,7], 'Groups.id' => $this->controllerUser['group_id'], 
				'GroupsUsers.net_id' => $this->controllerUser['net_id']]));
        } elseif ($this->controllerUser['isNodeCoordinator']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])
				->where(['Users.profile_id IN' => [4,5,6,7], 'Groups.id' => $this->controllerUser['group_id'], 
				'GroupsUsers.net_id' => $this->controllerUser['net_id'], 
                'GroupsUsers.main_gate' => $this->controllerUser['main_gate']]));
        } elseif ($this->controllerUser['isTacticOperator']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])
				->where(['Users.profile_id IN' => [4,5,6,7], 'Groups.id' => $this->controllerUser['group_id'], 
				'GroupsUsers.net_id' => $this->controllerUser['net_id'], 
                'GroupsUsers.main_gate' => $this->controllerUser['main_gate']]));
        } elseif ($this->controllerUser['isSanitaryAgent']){
            $users = $this->paginate($this->Users->find('search', ['search' => $this->request->getQuery()])->distinct(['Users.id'])
				->where(['Users.profile_id IN' => [4,5,6,7], 'Groups.id' => $this->controllerUser['group_id'], 
				'GroupsUsers.net_id' => $this->controllerUser['net_id'], 
                'GroupsUsers.main_gate' => $this->controllerUser['main_gate']]));
        }
        $this->set(compact('users'));
		$this->set('_serialize', ['users']);
    }

As you can see in the if statement I put the sql($query) and it doesn’t show the join between Users and GroupsUsers, this is what it shows:

SELECT 
  Users.id AS Users__id, 
  Users.username AS Users__username, 
  Users.password AS Users__password, 
  Users.email AS Users__email, 
  Users.firstname AS Users__firstname, 
  Users.lastname AS Users__lastname, 
  Users.created AS Users__created, 
  Users.modified AS Users__modified, 
  Users.profile_id AS Users__profile_id, 
  Users.referrer_id AS Users__referrer_id, 
  Users.active AS Users__active, 
  Users.image_file_name_url AS Users__image_file_name_url, 
  Users.image_file_name AS Users__image_file_name, 
  Users.image_file_name_filename AS Users__image_file_name_filename, 
  Users.map_lat AS Users__map_lat, 
  Users.map_long AS Users__map_long, 
  Users.code AS Users__code, 
  Users.status AS Users__status, 
  Users.isolated AS Users__isolated, 
  Users.token AS Users__token, 
  Profiles.id AS Profiles__id, 
  Profiles.name AS Profiles__name, 
  Profiles.description AS Profiles__description, 
  Profiles.referrer_profile_id AS Profiles__referrer_profile_id, 
  Profiles.created AS Profiles__created, 
  Profiles.modified AS Profiles__modified, 
  Referrer.id AS Referrer__id, 
  Referrer.username AS Referrer__username, 
  Referrer.password AS Referrer__password, 
  Referrer.email AS Referrer__email, 
  Referrer.firstname AS Referrer__firstname, 
  Referrer.lastname AS Referrer__lastname, 
  Referrer.created AS Referrer__created, 
  Referrer.modified AS Referrer__modified, 
  Referrer.profile_id AS Referrer__profile_id, 
  Referrer.referrer_id AS Referrer__referrer_id, 
  Referrer.active AS Referrer__active, 
  Referrer.image_file_name_url AS Referrer__image_file_name_url, 
  Referrer.image_file_name AS Referrer__image_file_name, 
  Referrer.image_file_name_filename AS Referrer__image_file_name_filename, 
  Referrer.map_lat AS Referrer__map_lat, 
  Referrer.map_long AS Referrer__map_long, 
  Referrer.code AS Referrer__code, 
  Referrer.status AS Referrer__status, 
  Referrer.isolated AS Referrer__isolated, 
  Referrer.token AS Referrer__token 
FROM 
  users Users 
  INNER JOIN profiles Profiles ON Profiles.id = Users.profile_id 
  LEFT JOIN users Referrer ON Referrer.id = Users.referrer_id 
WHERE 
  Users.profile_id in (1, 2, 3, 4, 5, 6, 7)

A hasMany relation will by default result in a second query happening, not through a join.

Ok, thank you, how do I have to do to retrieve the belongstomany associated groups with users?

What does debug($query->first()) give you?

First let me tell you that the first two users records don’t have a matching group, from the third users record on have a matching group.
This is what it shows debug($query->first()):

APP/Controller/UsersController.php (line 69)
object(App\Model\Entity\User) id:0 {
  'id' => (int) 1
  'username' => 'mdeanquin@gmail.com'
  'password' => '$2y$10$ecLkZ5vOgDts.X65L9ARKehxqeuiP/IzAqB0miUuKOZvRRFZS6C46'
  'email' => 'mdeanquin@gmail.com'
  'firstname' => 'Matías'
  'lastname' => 'de Anquin'
  'created' => object(Cake\I18n\FrozenTime) id:1 {
    'time' => '2023-03-23 12:01:19.000000-03:00'
    'timezone' => 'America/Argentina/Cordoba'
    'fixedNowTime' => false
  }
  'modified' => object(Cake\I18n\FrozenTime) id:2 {
    'time' => '2023-03-29 13:55:41.000000-03:00'
    'timezone' => 'America/Argentina/Cordoba'
    'fixedNowTime' => false
  }
  'profile_id' => (int) 1
  'referrer_id' => null
  'active' => true
  'image_file_name_url' => 'https://www.estadoatulado.com.ar/upload/Users/007.jpg'
  'image_file_name' => '/home/o12mg0png743/public_html/estadoatulado.com.ar/webroot/upload/Users/007.jpg'
  'image_file_name_filename' => '007.jpg'
  'map_lat' => null
  'map_long' => null
  'code' => '1234567890'
  'status' => (int) 0
  'isolated' => false
  'token' => null
  'groups_users' => [
  ]
  'referrer' => null
  'profile' => object(App\Model\Entity\Profile) id:3 {
    'id' => (int) 1
    'name' => 'Administrador'
    'description' => 'Administrador del sistema'
    'referrer_profile_id' => null
    'created' => object(Cake\I18n\FrozenTime) id:4 {
      'time' => '2023-03-13 21:34:40.000000-03:00'
      'timezone' => 'America/Argentina/Cordoba'
      'fixedNowTime' => false
    }
    'modified' => object(Cake\I18n\FrozenTime) id:5 {
      'time' => '2023-03-13 21:34:40.000000-03:00'
      'timezone' => 'America/Argentina/Cordoba'
      'fixedNowTime' => false
    }
    '[new]' => false
    '[accessible]' => [
      'name' => true,
      'description' => true,
      'referrer_profile_id' => true,
      'created' => true,
      'modified' => true,
      'aro' => true,
      'referrer_profile' => true,
      'profiles_gates' => true,
      'users' => true,
      'sourcing_events' => true,
    ]
    '[dirty]' => [
    ]
    '[original]' => [
    ]
    '[virtual]' => [
    ]
    '[hasErrors]' => false
    '[errors]' => [
    ]
    '[invalid]' => [
    ]
    '[repository]' => 'Profiles'
  }
  '[new]' => false
  '[accessible]' => [
    'username' => true,
    'password' => true,
    'email' => true,
    'firstname' => true,
    'lastname' => true,
    'full_name' => true,
    'created' => true,
    'modified' => true,
    'profile_id' => true,
    'referrer_id' => true,
    'active' => true,
    'image_file_name_url' => true,
    'image_file_name' => true,
    'image_file_name_filename' => true,
    'map_lat' => true,
    'map_long' => true,
    'code' => true,
    'status' => true,
    'isolated' => true,
    'token' => true,
    'aro' => true,
    'profile' => true,
    'referrer' => true,
    'statesx_days' => true,
    'doctors' => true,
    'events_users' => true,
    'observations' => true,
    'pacients' => true,
    'status_groups' => true,
    'stocks_users' => true,
    'turns' => true,
    'doctorT' => true,
    'groups' => true,
  ]
  '[dirty]' => [
  ]
  '[original]' => [
  ]
  '[virtual]' => [
  ]
  '[hasErrors]' => false
  '[errors]' => [
  ]
  '[invalid]' => [
  ]
  '[repository]' => 'Users'
}