Validation on two fields [Solved]


#1

In a Folders table, I need to prevent users to add a new folder with the same name in the same place.
So my validation rule should be “unique” on “Name” and “Path” (name and path are two fields in the DB).
Could someone help me on this ?


#2

https://book.cakephp.org/3.0/en/core-libraries/validation.html#custom-validation-rules


#3

Well, this does not help much as I already read this page.
I do not understand the way providers work.
This is my code :
$validator
->requirePresence(‘name’, ‘Same name and path !’, function ($context) {
$n = $this->find()->where([‘name’ => $context[‘data’][‘name’]]);
$p = $this->find()->where([‘path’ => $context[‘data’][‘path’]]);
if ($n && $p) {
return false;
}
});


#4

I tries another way that almost works but I still get an error :
Undefined index: path [ROOT/plugins/Medias/src/Model/Table/DossiersTable.php, line 98]

Here is my code :
$validator
->add(‘name’, ‘validNameAndPlace’, [
‘rule’ => ‘isValidNameAndPlace’,
‘message’ => __(‘A folder with the same name exists in this place. Please, choose another name.’),
‘provider’ => ‘table’,
])

public function isValidNameAndPlace($value, array $context)
{
    $n = $this->find()->where(['name' => $context['data']['name']]);
    $p = $this->find()->where(['path' => $context['data']['path']]);
    if ($n && $p) {
		return false;
    } else {
	    return true;
    }
}

#5

So it seems you validator does not get the path, as the error message states it.


#6

I am not sure about this, but I think $n and $p would be a Query object. So if you solved the path issue you should change your if statement to if ($n->first() && $p->first()) or something like this.


#7

I got it !
In fact, path was not set at create but after save (automatic field).
So I had that error as the field was not in the $context[‘data’].

I changed path for parent_id and voila.
My code :
$n = $this->find()->where([‘name’ => $context[‘data’][‘name’], ‘parent_id’ => $context[‘data’][‘parent_id’]])->first();
if ($n) {
return false;
} else {
return true;
}

Thank you for showing me a way.