Allow empty value in belongsto relation

I have two tables (users and affiliates) that I want to relate with affiliate_id in users table, but I want to allow null value in affiliate_id in some cases, how can I do that?

What do you currently have that’s blocking it?

I don’t know.
This is the code for UsersTable.php:

<?php
declare(strict_types=1);

namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

/**
 * Users Model
 *
 * @property \App\Model\Table\ProfilesTable&\Cake\ORM\Association\BelongsTo $Profiles
 *
 * @method \App\Model\Entity\User newEmptyEntity()
 * @method \App\Model\Entity\User newEntity(array $data, array $options = [])
 * @method \App\Model\Entity\User[] newEntities(array $data, array $options = [])
 * @method \App\Model\Entity\User get($primaryKey, $options = [])
 * @method \App\Model\Entity\User findOrCreate($search, ?callable $callback = null, $options = [])
 * @method \App\Model\Entity\User patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
 * @method \App\Model\Entity\User[] patchEntities(iterable $entities, array $data, array $options = [])
 * @method \App\Model\Entity\User|false save(\Cake\Datasource\EntityInterface $entity, $options = [])
 * @method \App\Model\Entity\User saveOrFail(\Cake\Datasource\EntityInterface $entity, $options = [])
 * @method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface|false saveMany(iterable $entities, $options = [])
 * @method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface saveManyOrFail(iterable $entities, $options = [])
 * @method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface|false deleteMany(iterable $entities, $options = [])
 * @method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface deleteManyOrFail(iterable $entities, $options = [])
 *
 * @mixin \Cake\ORM\Behavior\TimestampBehavior
 */
class UsersTable extends Table
{
    /**
     * Initialize method
     *
     * @param array $config The configuration for the Table.
     * @return void
     */
    public function initialize(array $config): void
    {
        parent::initialize($config);

        $this->setTable('users');
        $this->setDisplayField('username');
        $this->setPrimaryKey('id');

        $this->addBehavior('Timestamp');

		$this->addBehavior('Search.Search');

		$this->searchManager()
			->value('username')
			->value('email')
			->add('search', 'Search.Like', [ 
				'before' => true,
				'after' => true,
				'fieldMode' => 'OR',
				'comparison' => 'LIKE',
				'wildcardAny' => '*',
				'wildcardOne' => '?',
				'fields' => ['username','email']
		]);

        $this->belongsTo('Profiles', [
            'foreignKey' => 'profile_id',
            'joinType' => 'INNER',
        ]);
        $this->belongsTo('Affiliates', [
            'foreignKey' => 'affiliate_id',
            'joinType' => 'LEFT',
        ]);
    }

    /**
     * Default validation rules.
     *
     * @param \Cake\Validation\Validator $validator Validator instance.
     * @return \Cake\Validation\Validator
     */
    public function validationDefault(Validator $validator): Validator
    {
        $validator
            ->integer('id')
            ->allowEmptyString('id', null, 'create');

        $validator
            ->scalar('username')
            ->maxLength('username', 100)
            ->allowEmptyString('username');

        $validator
            ->scalar('password')
            ->maxLength('password', 100)
            ->allowEmptyString('password');

        $validator
            ->email('email')
            ->allowEmptyString('email');

        $validator
            ->scalar('firstname')
            ->maxLength('firstname', 100)
            ->allowEmptyString('firstname');

        $validator
            ->scalar('lastname')
            ->maxLength('lastname', 100)
            ->allowEmptyString('lastname');

        $validator
            ->boolean('active')
            ->notEmptyString('active');

        $validator
            ->scalar('token')
            ->maxLength('token', 100)
            ->requirePresence('token', 'create')
            ->allowEmptyString('token');

        $validator
            ->integer('affiliate_id')
            ->allowEmptyString('affiliate_id', null);

        return $validator;
    }

    /**
     * Returns a rules checker object that will be used for validating
     * application integrity.
     *
     * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
     * @return \Cake\ORM\RulesChecker
     */
    public function buildRules(RulesChecker $rules): RulesChecker
    {
        $rules->add($rules->isUnique(['username']), ['errorField' => 'username']);
        $rules->add($rules->isUnique(['email']), ['errorField' => 'email']);
        $rules->add($rules->existsIn(['profile_id'], 'Profiles'), ['errorField' => 'profile_id']);
        $rules->add($rules->existsIn(['affiliate_id'], 'Affiliates'), ['errorField' => 'affiliate_id']);

        return $rules;
    }
}

This is the code for add.php:

<?php
/**
 * @var \App\View\AppView $this
 * @var \App\Model\Entity\User $user
 */
?>
<div class="row">
    <aside class="column">
        <div class="side-nav">
            <h4 class="heading"><?= __('Acciones') ?></h4>
            <?= $this->Html->link(__('Listar Usuarios'), ['action' => 'index'], ['class' => 'side-nav-item']) ?>
        </div>
    </aside>
    <div class="column-responsive column-80">
        <div class="users form content">
            <?= $this->Form->create($user) ?>
            <fieldset>
                <legend><?= __('Agregar Usuario') ?></legend>
                <?php
                    echo $this->Form->control('username', ['label' => 'Nombre de usuario']);
                    echo $this->Form->control('password', ['label' => 'Contraseña']);
                    echo $this->Form->control('email', ['label' => 'E-mail']);
                    echo $this->Form->control('firstname', ['label' => 'Nombre']);
                    echo $this->Form->control('lastname', ['label' => 'Apellido']);
                    echo $this->Form->control('profile_id', ['label' => 'Perfil', 'empty' => '- Seleccione un perfil -', 'options' => $profiles]);
                    echo '<div id="selectAffiliate" style="display:none;">'.$this->Form->control('affiliate_id', ['label' => 'Afiliado', 'empty' => '- Seleccione un afiliado -', 'options' => $affiliates]).'</div>';
                    echo $this->Form->control('active', ['label' => 'Activo']);
                ?>
            </fieldset>
            <?= $this->Form->button(__('Submit')) ?>
            <?= $this->Form->end() ?>
        </div>
    </div>
</div>
<script>
$(function(){
	$('#profile-id').change(function(){
		var profile_id = $(this).val();
		if(profile_id=="5") $('#selectAffiliate').show();
		else $('#selectAffiliate').hide();
	})
})
</script>

And this is the code for add action in UsersController.php:

    public function add()
    {
		$user = $this->Users->newEmptyEntity();
        if ($this->request->is('post')) {
            $user = $this->Users->patchEntity($user, $this->request->getData());
            if ($this->Users->save($user)) {
                $this->Flash->success(__('El usuario ha sido guardado.'));
				$result = $this->Authentication->getResult();
				// If the user is logged in send them away.
				if ($result->isValid()) {
					return $this->redirect(['action' => 'index']);
				}else{
					return $this->redirect(['action' => 'login']);
				}
            }
            $this->Flash->error(__('El usuario no pudo ser guardado. Por favor, intente nuevamente.'));
        }
        $profiles = $this->Users->Profiles->find('list', ['limit' => 200]);
        $affiliates = $this->Users->Affiliates->find('list', ['limit' => 200]);
        $this->set(compact('user', 'profiles', 'affiliates'));
    }

As you can see the affiliate_id control is hidden for the user, but I show it with jquery when the user selects profile_id number 5.
But even when I select an affiliate it doesn’t save the user.

I solved it, the problem was here;

$validator
            ->scalar('token')
            ->maxLength('token', 100)
            ->requirePresence('token', 'create')
            ->allowEmptyString('token');

I eliminated it and worked fine