Conditional validation on edit of object

Hmm.

A bit of context: this is a Trip table which has multiple "price’ columns; only one of them needs to be filled in, depending on the type of the trip, but it must be filled in. So I created conditional validation rules on my model:

public function validationDefault (Validator $validator)
{
  $validator->notEmpty ('offered_price', __ ('De prijs moet ingevuld worden'), function ($context)
  {
    return $context['data']['trip_type'] == 'bulk';
   });
   ... similar rules for other trip_types...
}

This works perfectly when adding a new trip; but when editing an existing object, I see this error in the form:

$this->Form->create($trip);
print $this->Form->control('offered_price');

The last line results in this notice:

[ **Notice** (8)] Undefined index: trip_type [ **....Model/Table/TripsTable.php** , line **68** ]

I found this post in the forums which explains that $context[‘data’] is only valid when patchEntity is called. That makes sense, but I’m only building up the form, not processing it. I think FormHelper uses the same rules to mark fields as required, but how to provide the correct data? I’m sure everybody that uses conditional validations has run into this problem, maybe someone has an elegant solution? The ‘answer’ in the post above (“pass it as provider”) does not provide any clues as how to accomplish this.

well you do as in post - give your original data as provider or just give it necessary data to your patchEntity

$data = $this->request->getData() + ['trip_type' => $trip->trip_type];
$this->Trips->patchEntity($trip, $data);

I’m not doing anything with the data, I’m just generating the form (I updated the question to highlight where the error occurs).

you are only giving offered_price in $context['data'] so you get error of Undefined index: trip_type you need to supply it (trip_type) somehow, i gave you 2 options to do it

I understand why I get an Undefined index, just asking if there is an elegant way to prevent it…
As to the provider, I read the post and the link to Validation class, it just doesn’t make much sense that I have to do things double and at different places (Controller and Model). The data is there, it is provided to the FormHelper with create() (the $trip object is filled with the existing data), why can’t I use it? Again, I am not validating anything, not processing the form, just generating it.

maybe something like

https://book.cakephp.org/3.0/en/orm/validation.html#validating-data-before-building-entities

$article = $articles->newEntity(
    $this->request->getData(),
    ['validate' => false]
);

it will skip validation, usefull when you just want entity for your form

Your validation function should check whether there is data provided, and behave as required for the other scenario when there isn’t.

Yes, I wrapped the check in an

if (!empty($context['data']))
{
 ...
}

However, marking it as required makes it impossible to submit the form since there will be a “required” attribute in the <input> tag, even the fields that are currently hidden. But not making it non-required is not a problem since the validation will kick in again when submitting the data.

Does adding } else { return false; } improve the situation?

Not in all cases; the various allowEmpty* / notEmpty functions seem to have different opinions on what to return (true or false). In the end I will remove the conditional checks, or replace them with various validation sets that are manually selected when processing the form (there are too many interdependencies).