# CakePHP 4 Validation of two fields

**URL:** <https://discourse.cakephp.org/t/cakephp-4-validation-of-two-fields/10616>\
**Category:** Need Help\
**Created:** [September 8, 2022, 1:11am UTC](https://discourse.cakephp.org/t/cakephp-4-validation-of-two-fields/10616 "2022-09-08T01:11:39Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![cwstarkey](https://avatars.discourse-cdn.com/v4/letter/c/6a8cbe/32.png) [@cwstarkey](https://discourse.cakephp.org/u/cwstarkey)\
**Post date:** [September 8, 2022, 1:11am UTC](https://discourse.cakephp.org/t/cakephp-4-validation-of-two-fields/10616/1 "2022-09-08T01:11:39Z")

</div>

A form includes two fields where one must be populated, but only one.

I have written two rules (below), the first works, producing an error when both fields are populated. The second does not, allowing both fields to be empty (when we must have one). What am I missing?

```auto
        $validator->add('labor', 'custom', [
            'rule' => function ($value, $context) {
                if (!empty($context['data']['labor']) && !empty($context['data']['flat_rate'])) {
                    return false;
                }
                return true;
            },
            'message' => 'You cannot define both a flat rate and a labor time. Assign labor when parts can be expected.'
        ]);
        
        $validator->add('flat_rate', 'custom', [
            'rule' => function ($value, $context) {
                if (empty($context['data']['labor']) && empty($value)) {
                    return false;
                }
                return true;
            },
            'message' => 'You must define either a flat rate or a labor time. Assign labor when parts can be expected.'
        ]);

```

Thank you for your help!

---

<div class="post-metadata">

**Author:** ![Zuluru](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/zuluru/32/1230_2.png) [@Zuluru](https://discourse.cakephp.org/u/Zuluru)\
**Post date:** [September 8, 2022, 1:43am UTC](https://discourse.cakephp.org/t/cakephp-4-validation-of-two-fields/10616/2 "2022-09-08T01:43:08Z")

</div>

When both fields are empty, and the second one is called, what do `$value` and `$context` hold?

---

<div class="post-metadata">

**Author:** ![cwstarkey](https://avatars.discourse-cdn.com/v4/letter/c/6a8cbe/32.png) [@cwstarkey](https://discourse.cakephp.org/u/cwstarkey)\
**Post date:** [September 12, 2022, 10:33pm UTC](https://discourse.cakephp.org/t/cakephp-4-validation-of-two-fields/10616/3 "2022-09-12T22:33:38Z")

</div>

Sorry for the long delay Zuluru, and you responded so quickly.

Your question helps. This may be a given, I’m still learning. It appears the validator is only called when the field has a value. What I’m trying to do is require one of the two to be populated (both cannot be empty, nor should both be populated). So the first validator (labor) is working as designed (failing if both are populated), but the second (flat\_rate) is only called when flat\_rate has a value (so it will never fail when both are empty).

---

<div class="post-metadata">

**Author:** ![Zuluru](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/zuluru/32/1230_2.png) [@Zuluru](https://discourse.cakephp.org/u/Zuluru)\
**Post date:** [September 13, 2022, 2:29am UTC](https://discourse.cakephp.org/t/cakephp-4-validation-of-two-fields/10616/4 "2022-09-13T02:29:32Z")

</div>

Depends on what you mean by “has a value”, I think? Validators are only called when the field is present in the provided data, but the value could be blank. Sounds like maybe what you want is more of a rule than a validation.

---

<div class="post-metadata">

**Author:** ![cwstarkey](https://avatars.discourse-cdn.com/v4/letter/c/6a8cbe/32.png) [@cwstarkey](https://discourse.cakephp.org/u/cwstarkey)\
**Post date:** [September 13, 2022, 10:35am UTC](https://discourse.cakephp.org/t/cakephp-4-validation-of-two-fields/10616/5 "2022-09-13T10:35:20Z")

</div>

I think you’re right. I’ll look at it from that angle, thank you!

---

<div class="post-metadata">

**Author:** ![dreamingmind](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/dreamingmind/32/1857_2.png) [@dreamingmind](https://discourse.cakephp.org/u/dreamingmind)\
**Post date:** [September 15, 2022, 4:01am UTC](https://discourse.cakephp.org/t/cakephp-4-validation-of-two-fields/10616/6 "2022-09-15T04:01:41Z")

</div>

I would be writing a Rule rather than a Validator for this.

As the [validation documentation](https://book.cakephp.org/4/en/orm/validation.html#validating-data) explains:

1. Before request data is converted into entities, _ **validation** _ rules around data types and formatting can be applied.
2. Before data is saved, domain or application _ **rules** _ can be applied. These rules help ensure that your application’s data remains consistent.

To be clear

- Validations enforce data types
- Rules enforce logic

Your case is a clear example of enforcing business rules (logic)

The key advantage in this case is that your Rule will receive the entire entity as one of the arguments and this will make it simple to write the logic you require.

Read about [Rules here](https://book.cakephp.org/4/en/orm/validation.html#applying-application-rules).
