Dallaylaen has asked for the wisdom of the Perl Monks concerning the following question:

Hello, dear esteemed monks!

tl;dr: I'm thinking of a module that (1) compiles a set of validation rules once and (2) for each hashref given to it later, returns another object containing valid data, errors, AND initial input for processing and/or resubmission.

Is there such a module already? If not, should I roll my own? If yes, does the API described below seem sensible?

Now the whole story. Some time ago there was a discussion here at Perlmonks pointing out that it would be nice to make create button act as preview if post content was edited. Can't find proofs now, but the idea impressed me much.

Recently I started looking for a form validator. My initial idea was to build a permanent validator object once and keep throwing inputs at it later. And I found a module with almost the interface I imagined - Validator::LIVR.

However, after trying to actually implement form validation & resubmission, I found myself juggling 3 hashrefs (valid data, errors, raw user input for reentry). This was not very convenient, so I decided to pack them into one object, adding is_valid() method on top. And I found a module on CPAN with almost the interface I imagined (but without the "compile once" part) - Data::CGIForm.

So I crossed these two and got roughly the following API:

# initialization # the hash describes regexps, requiredness, and other checks # per input key my $validator = My::Class->new ( { ... } ); # later when processing request my $form = $validator->validate( { get => "params" } ); if ($form->is_valid) { do_something( $form->data ); redirect( "/somewhere" ); } else { show_form_again( display_errors => $form->error, input_defaults => + $form->raw ); };

Also error content (and thus is_valid return value) can be modified, just like in Data::CGIForm:

if (!load_user($form->data->{user})) { $form->error( user => "No such user in database" ); };

Unfortunately, the Data::CGIForm has a fatal flaw: error() without arguments acts like my is_valid(), while separate errors() method returns all errors as hash. Error/errors is prone to typoes in my opinion, but maybe I should shut up my ego and stay compatible to an existing API instead?

Thank you

Replies are listed 'Best First'.
Re: Module for form validation and resubmission
by Your Mother (Archbishop) on Oct 21, 2016 at 13:20 UTC

    There is also HTML::FormFu with which I have had a love/hate relationship. It's big, complicated, and slow but reminds me of the chestnut about democracy: it's the worst form of government there is, except for all the others. FormFu seems like overkill until you end up writing/tailoring just about everything it does from scratch, then it starts to seem pretty cool that at least FormFu has documentation. :P I don't know Validator::LIVR so can't accurately compare it. A casual read of its POD leads me to believe it's approximately FormFu-lite though I would also expect it to be much faster.

    Your real question: stick to the API. If you feel it really isn't right, write a patch and submit a pull request to the project. Trying to correct the way an API behaves, or force it to your comfort zone, complicates the plumbing quickly and is prone to maintenance nightmares which is pressure to abandonment.

      HTML::FormFu has a prohibitive dependency footprint. Fine in a centralized project, but forcing that on someone else - and I'm going to distribute my work - seems too much to me.

      As for DATA::CGIForm, I'm not using or extending it in any way. Should that be the case, changing the API would be out of question. Neither am I planning a drop-in replacement, due to the initialization phase.

      But if it's popular and widely used, mimicking its API could still be worthy due to the least astonishment principle... That's why I'm asking.

      Actually I seem to have found a way to stay backward compatible with Data::CGIForm that doesn't irritate me. Thanks for your feedback.