# How to? Validation of self referencing table data

**URL:** <https://discourse.cakephp.org/t/how-to-validation-of-self-referencing-table-data/4970>\
**Category:** Uncategorized\
**Created:** [September 20, 2018, 7:47pm UTC](https://discourse.cakephp.org/t/how-to-validation-of-self-referencing-table-data/4970 "2018-09-20T19:47:37Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![bird](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/bird/32/1157_2.png) [@bird](https://discourse.cakephp.org/u/bird)\
**Post date:** [September 20, 2018, 7:47pm UTC](https://discourse.cakephp.org/t/how-to-validation-of-self-referencing-table-data/4970/1 "2018-09-20T19:47:37Z")

</div>

Hi,

I have a hasMany relation between the tables “machines” and “machine\_parts”.

The user uploads an XML file with a whole machine: some header-information and the parts, the machine consists of.

Here comes my problem:

Machine parts can be mounted on each other. This field (mounted\_on) can also be empty.

Before saving the data I want to validate if all machine parts with the mounted\_on field set contain a valid reference to an existing machine part.

The validation errors should be attached to the “mounted\_on” field.

I wasn’t able to achive this with custom validation rules, because `$context` gives me only access on an entity (row) level. I wasn’t able to access the whole array of “machine\_parts”.

```auto
    'rule' => function ($value, $context) 

```

I was able to get my desired behavior within the buildRules-Event. But this feels quite hacky because there I’m using `->setError(...)` to inject the errors on the field level.

How ist this done in the cakephp-way? Is my approach right?

* * *

* * *

* * *

P.S.: The reason why I choose to do the validation on the table level and not inside the xml-parser was that I want to keep all the validation in one place.

Another approach could be to add methods to the “machine\_parts”-table that set a property containing invalid “mounted\_on”-fields. Then I could compare them in the validation rules with [-\>inList()](https://api.cakephp.org/3.6/source-class-Cake.Validation.Validation.html#1029-1047). Maybe this works with beforeMarshal. Seems a “cleaner” solution to me. But still feels hacky.

I’ll try this tomorrow. Hope someone can point me in the right direction.

---

<div class="post-metadata">

**Author:** ![rrd](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/rrd/32/113_2.png) [@rrd](https://discourse.cakephp.org/u/rrd)\
**Post date:** [September 21, 2018, 10:49am UTC](https://discourse.cakephp.org/t/how-to-validation-of-self-referencing-table-data/4970/2 "2018-09-21T10:49:14Z")

</div>

You have to use application rules  
[https://book.cakephp.org/3.0/en/orm/validation.html#applying-application-rules](https://book.cakephp.org/3.0/en/orm/validation.html#applying-application-rules)

---

<div class="post-metadata">

**Author:** ![bird](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/bird/32/1157_2.png) [@bird](https://discourse.cakephp.org/u/bird)\
**Post date:** [September 21, 2018, 2:15pm UTC](https://discourse.cakephp.org/t/how-to-validation-of-self-referencing-table-data/4970/3 "2018-09-21T14:15:58Z")

</div>

Thank you for your hint.

> [@rrd](#):
>
> You have to use application rules

I did exactly this (in the `MachinesTable`). **But** this way the errors obviously don’t get attached to the machine part field (mounted\_on) but on the association (mounted\_parts).

My current rule in the `MachinesTable` looks like the following code. It works, but feels quite hacky. Isn’t there any possibility without setting the errors manually on the associated data?

```PHP
$rules->add(function ($entity, $options) {
            $invalidMountPoints = $this->getInvalidMountpoints($entity['machine_parts']);
            return $this->setErrorOnAssociated(
                $invalidMountPoints,
                'mounted_on',
                __('machine_parts.validation_error.mounted_on_does_not_exist')
            );
        },
        'checkMounPointExists');

    /**
     * Set errors on an associated entity
     *
     * @param array &$errEntities an array containing entities with errors
     * @param string $field The field on which the error should be set
     * @return bool Returns true if the entity contains no errors
     */
    public function setErrorOnAssociated(?array &$errEntities, string $field, string $errorMsg): bool
    {
        if(!empty($errEntities)) {
            foreach($errEntities as &$errEntity) {
                $errEntity->setError($field, $errorMsg);
            }
            return false;
        }
        return true;
    }

```

---

<div class="post-metadata">

**Author:** ![rrd](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/rrd/32/113_2.png) [@rrd](https://discourse.cakephp.org/u/rrd)\
**Post date:** [September 22, 2018, 9:40am UTC](https://discourse.cakephp.org/t/how-to-validation-of-self-referencing-table-data/4970/4 "2018-09-22T09:40:38Z")

</div>

It does not seems hacky to me. And I think you do not have any other options.

---

<div class="post-metadata">

**Author:** ![Graziel](https://avatars.discourse-cdn.com/v4/letter/g/71c47a/32.png) [@Graziel](https://discourse.cakephp.org/u/Graziel)\
**Post date:** [September 22, 2018, 5:58pm UTC](https://discourse.cakephp.org/t/how-to-validation-of-self-referencing-table-data/4970/5 "2018-09-22T17:58:28Z")

</div>

for validation you can set provider as any object even your missing `machine_parts`  
[https://book.cakephp.org/3.0/en/core-libraries/validation.html#adding-validation-providers](https://book.cakephp.org/3.0/en/core-libraries/validation.html#adding-validation-providers)

```php
$this->MachineParts
     ->getValidator('default')
     ->setProvider('machine_parts', $machine->machine_parts);

```

then you can access it in your custom validation rule from `$context['providers']['machine_parts']`  
[https://book.cakephp.org/3.0/en/core-libraries/validation.html#using-custom-validation-rules](https://book.cakephp.org/3.0/en/core-libraries/validation.html#using-custom-validation-rules)
