Possible bug in updating field values from hasOne->addField

I’ve noticed something that I think may be a bug. I have a Model that gets some fields from another model. The other model defines certain parameters about that kind of model. The init function of Model ‘Thing’ looks something like:

$this->hasOne(‘thingType_id’, [new ThingType(), ‘required’ => true)->addFields([‘hasRed’, ‘hasBlue’]);

I’d like to allow the user to change a Thing to a new ThingType, but include validation based on the new fields. For the example above, let’s say that hasRed is a boolean. Assume that the Thing record initially is set to a ThingType where hasRed is true. Under certain conditions, I’d like to require that the ThingType be one where hasRed is true. I therefore have the following validation hook in Thing’s definition:

$this->addHook(‘validate’, function ($m) {
if (!$m[‘hasRed’]) return ([‘thingType_id’ => ‘You must choose a type with hasRed’]);
});

The problem I’m seeing is that when the user chooses a new ThingType in my form and hits save, my
validation routine is called – but the value of hasRed is the valid from the thingType_id from when the
record was loaded, not the one from the new thingType_id that the user choose. It appears that the values of the fields imported by hasOne->addField are only loaded on record load, not when the hasOne field changes. For the purposes of the validation routine, I can manually load the record for the new thingType_id and get around this issue, so there’s no big deal (but it’s awkward).

However, I’d also like to display the fields imported by hasOne->addField in my Thing form. I write the straightforward code to do so, and everything looks fine – until the user chooses a new thingType_id. The displayed values of hasRed and hasBlue remain unchanged. Unlike with the validation hook, I can’t think of a way around this.

Am I correct in saying that field values from hasOne->addFields are only updated on record load, and not prior to a save/reload? Should this be considered a bug? Is there a way for me to change the behavior to what I would consider expected, i.e., if $m->isDirty(‘thingType_id’) then all of the fields from the addField are reloaded based on the new thingType_id and considered dirty (or, if it’s real fancy, compares each those fields between the old and new thingType_id and only considers the changed ones dirty)?

Thanks for any thoughts you have on this.

Hi.

Validation based on related objects is quite complex and you might need tweak your validation routine. There may not be a correct way (for a framework) to do anything here. In a situation like that - ATK guidelines ask not to implement anything.

You can implement add-on with custom validation and custom UI - if that can be adopted by others easily, it would be valuable, however it won’t constrain other users who wish to implement things in a different way.

I appreciate the feedback, but that’s not quite what I was saying. The validation was not really the issue – the validation routine was only where I noticed the issue. The issue was not that I was having trouble validating things, but that the data from the related fields pulled in through the hasOne that I was accessing wasn’t being updated when the field changed. My current theory is that it’s updated only on model load.

In my original post I also provided the example of an input/modify form that might be used by a CRUD. If the user changes the hasOne field pointing at the other model, the fields from the other table aren’t updated to the new values, so the CRUD form displays the wrong data.

The only thing I’m suggesting might need to be changed (or looking for a way I can set things up to do this) is that the fields pulled in by a hasOne->addField be updated when the base hasOne field is changed, whether that’s prior to the validation so that it’s available for the validation, available for a user form that may simply be displaying the data, or any other reason.