Using ->set(false)->get(false) for field validation on non-database fields
Using ->set(false)->get(false) for field validation on non-database fields
Loren Maxwell
Posts: 490Questions: 120Answers: 10
Just a quick note for anyone that might find it helpful (plus a small suggestion for @allan at the end!):
Out of the box, Editor has very useful server-side field validation:
https://editor.datatables.net/manual/php/validation
(Lately I've especially taken advantage of the relatively new dependsOn() method!)
But occasionally data is submitted from the client-facing fields that don't match the fields in my table.
These non-database fields are used to do other things on the backend, but my point here is that I've previously done validation on those non-database fields in a global validator, which doesn't allow me to use the built-in field validation tools from Editor and also returns a global error instead of a field-specific one, so the UI isn't as helpful.
MY OLD WAY
// Requires: id, player_code, and school_code (all database fields)
// And either school_code or school_name_manual (not database fields) for other processing
Editor::inst( $db, 'players_seasons' )
->fields(
Field::inst( 'id' ),
Field::inst( 'player_code' )
->validator( 'Validate::notEmpty' ),
Field::inst( 'season_code' )
->validator( 'Validate::notEmpty' )
)
// Non-database fields checked in a global validator
->validator( function ( $editor, $action, $data ) {
if ( $action === Editor::ACTION_CREATE ) {
foreach ( $data['data'] as $pkey => $values ) {
if (
empty($values['school_code'])
&& empty($values['school_name_manual'])
) {
return "School cannot be blank";
}
return true;
}
}
return true;
});
However I've recently realized that by using both set(false) and get(false), the server-side Editor will accept those non-database fields without fussing they don't match the fields in the table and I can use field validation:
MY NEW WAY
// Requires: id, player_code, and school_code (all database fields)
// And either school_code or school_name_manual (not database fields) for other processing
Editor::inst( $db, 'players_seasons' )
->fields(
Field::inst( 'id' ),
Field::inst( 'player_code' )
->validator( 'Validate::notEmpty' ),
Field::inst( 'season_code' )
->validator( 'Validate::notEmpty' ),
// Non-database fields checked in a field validator
// with ->set(false)->get(false)
Field::inst( 'school_name_manual' )->set(false)->get(false),
Field::inst( 'school_code' )->set(false)->get(false),
->validator( Validate::notEmpty( ValidateOptions::inst()
->message( 'School cannot be blank' )
->dependsOn(function ($val, $row, $host) {
return empty($row['school_name_manual']);
})
))
);
This does the same thing except it's cleaner coding and the error for a missing school_code and school_name_manual shows on the client side under the specific field the client sees.
Suggestion for @allan would be to include an ignore() method (or submit(false) or something similar) that would do the same as the ->set(false)->get(false), such as:
SUGGESTION
// Requires: id, player_code, and school_code (all database fields)
// And either school_code or school_name_manual (not database fields) for other processing
Editor::inst( $db, 'players_seasons' )
->fields(
Field::inst( 'id' ),
Field::inst( 'player_code' )
->validator( 'Validate::notEmpty' ),
Field::inst( 'season_code' )
->validator( 'Validate::notEmpty' ),
// Non-database fields
// with ->ignore() (or submit(false) or something similar)
Field::inst( 'school_name_manual' )->ignore(),
Field::inst( 'school_code' )->ignore(),
->validator( Validate::notEmpty( ValidateOptions::inst()
->message( 'School cannot be blank' )
->dependsOn(function ($val, $row, $host) {
return empty($row['school_name_manual']);
})
))
);
Replies
Many thanks for the suggestion! I'll certainly consider it. I'm a little worried about making the API surface bigger than it needs to be, but I can see the utility here.
Thanks for posting this so others can see your solution as well.
Allan