Cake 5.1: Model => Table => validator

Hi,
I have 2 fields “partner_id” and “center_id” and I would like to do a validation where at least one of them must be filled in, but not both.

This format works only if both fields are filled.

        $validator
            ->integer('partner_id')
            ->allowEmptyString('partner_id');

        $validator
            ->integer('center_id')
            ->allowEmptyString('center_id');        
        
        $validator
            ->add('center_id', 'partner-or-centre', [
                'rule' => function ($fromCentre, $context) {
                    $fromPartner = $context['data']['partner_id'] ?? null;
        
                    return (!empty($fromPartner) xor !empty($fromCentre)); // Použití XOR
                },
                'message' => __('Must select one of them not both'),
            ]);

Can someone please tell me what is correct way?

Thank you.

Just write a custom rule that looks also in the data in context and each returns true if there is at least value or the context data field data set.

Hi,
thank you for kick :wink: sometimes i need it.
I am not sure if it’s correct way, bud this works for me:

        $validator
            ->add('partner_id', 'one-required', [
                'rule' => function ($value, $context) {
                    $fromPartner = $value;
                    $fromCentre = $context['data']['centre_id'] ?? null;

                    return (!empty($fromPartner) xor !empty($fromCentre));
                },
                'message' => __('You must select Supplier or Centre, but not both')
            ]);

        $validator
            ->add('centre_id', 'one-required', [
                'rule' => function ($value, $context) {
                    $fromPartner = $context['data']['partner_id'] ?? null;
                    $fromCentre = $value;

                    return (!empty($fromPartner) xor !empty($fromCentre));
                },
                'message' => __('You must select Supplier or Centre, but not both')
            ]);

And in template i must make this (because I need to be able to select an empty value):

                    echo $this->Form->control('partner_id', [
                        'options' => $fromPartners,
                        'class' => 'form-control',
                        'label' => __('Supplier'),
                        'empty' => __('Select supplier or leave empty'),
                        'required' => false
                    ]);
                    echo $this->Form->control('centre_id', [
                        'options' => $fromCentres,
                        'class' => 'form-control',
                        'label' => __('Accounting Centre'),
                        'empty' => __('Select centre or leave empty'),
                        'required' => false
                    ]);

Maybe it helps somebody.

This is validator, what you are using:

$validator
            ->integer('partner_id')
            ->allowEmptyString('partner_id');

But it should look like

$validator
            ->integer('partner_id')
            ->notEmptyString('partner_id');

Hi efjot,
but I need to be able to select empty values.

Allowed combination:

  • empty partner_id + selected centre_id
  • empty centre_id + selected partner_id

Forbidden combination:

  • empty partner_id + empty centre_id
  • selected partner_id + selected centre_id

Regards, Kuba