Object oriented form parsing

A

A. Sinan Unur

Hello:

I am testing out an idea and trying to see whether it makes sense.

I have a pretty basic CGI application that has multiple forms with a
number of common elements on them. But depending on application state
some elements may appear on a given form and others may not.

I thought it might make sense to encapsulate the validation and
untainting of input in a simple object. For example:

package Ulti::param::period;

use strict;
use warnings;

use Regexp::Common qw(number);

sub new {
my $class = shift;
my $self = eval {
defined $_[0] or die;
my $value = $_[0];
$value =~ /^\s*$RE{num}{int}{-keep}\s*$/ or die;
$value = 0 + $1;
(0 <= $value) or die;
return $value;
};

return bless \$self, $class if defined $self;
return;
}

sub value { ${$_[0]}; }

1;
__END__


In addition, corresponding to each form that needs to be processed, there
is an object that handles the validation of all elements on that form.
For example:

package Ulti::Form::SubmitEditSession;

use Ulti::param::Endowment;
use Ulti::param::ExchangeRate;
use Ulti::param::GroupSize;
use Ulti::param::Matching;
use Ulti::param::paramName;
use Ulti::param::payoffMethod;
use Ulti::param::period;
use Ulti::param::Role;
use Ulti::param::SessionID;

sub new {
my $class = shift;
my $self = { };
return bless $self, $class;
}

sub validate {
my ($self, $cgi) = @_;

if(my $v = Ulti::param::period->new($cgi->param('practice_periods')))
{
$self->{'param'}->{'practice_periods'} = $v->value;
}
else
{
$self->{'error'} = 'practice_periods';
return;
}

# validate the rest of the inputs

return $self->{'param'};
}

sub error { return $_[0]->{'error'}; }

1;
__END__

And then, in the main code, I use:

sub submit_edit_session {
my $app = shift;

my $form = Ulti::Form::SubmitEditSession->new;
my $params = $form->validate($app->query);

unless( $params ) { return $app->show_error($form->error); }

# do something with $params
}

Is this reasonable at all? What problems do you see? I have tried using
CGI::Untaint but somehow the method above fits better with the way my
mind works, but I would like to get some advice from better minds than
mine before commiting to it.

Sinan.
 
B

Ben Morrow

Quoth "A. Sinan Unur said:
I have a pretty basic CGI application that has multiple forms with a
number of common elements on them. But depending on application state
some elements may appear on a given form and others may not.

I thought it might make sense to encapsulate the validation and
untainting of input in a simple object. For example:

package Ulti::param::period;

use strict;
use warnings;

use Regexp::Common qw(number);

sub new {
my $class = shift;

In addition, corresponding to each form that needs to be processed, there
is an object that handles the validation of all elements on that form.
For example:

package Ulti::Form::SubmitEditSession;

use Ulti::param::Endowment;
use Ulti::param::ExchangeRate;
use Ulti::param::GroupSize;
use Ulti::param::Matching;
use Ulti::param::paramName;
use Ulti::param::payoffMethod;
use Ulti::param::period;
use Ulti::param::Role;
use Ulti::param::SessionID;

Purely as a matter of taste, rather than having all these different
classes I would have one class, Ulti::param, with multiple constructors
named after the parameter name. These would be called like:
sub validate {
my ($self, $cgi) = @_;

if(my $v = Ulti::param::period->new($cgi->param('practice_periods')))

if ( my $v = Ulti::param->period($cgi->param('practice_periods') ) {

Similarly for the forms. I would also be strongly tempted to pass the
whole CGI object and a param name in, so that the param could if
necessary validate its consistency with the others on the form.
{
$self->{'param'}->{'practice_periods'} = $v->value;

All those quotes and the second -> are unnecessary:

$self->{param}{practice_periods} = $v->value;

Ben
 
A

A. Sinan Unur

Thank you very much for the comments. Our block was hit by lightning last
night just as I was responding to them. I don't know what that means :)
....

....


Purely as a matter of taste, rather than having all these different
classes I would have one class, Ulti::param, with multiple
constructors named after the parameter name.

That makes a whole lot more sense. After all, the code above was beginning
to look like Java rather than Perl.
These would be called like:


if ( my $v = Ulti::param->period($cgi->param('practice_periods') ) {

Similarly for the forms. I would also be strongly tempted to pass the
whole CGI object and a param name in, so that the param could if
necessary validate its consistency with the others on the form.

Got it.
All those quotes and the second -> are unnecessary:

Yeah, I do know better, but thanks for pointing it out.

I am going to go with the changes you suggested.

SInan.
 
D

David K. Wall

A. Sinan Unur said:
I am testing out an idea and trying to see whether it makes sense.

I have a pretty basic CGI application that has multiple forms with
a number of common elements on them. But depending on application
state some elements may appear on a given form and others may not.

I thought it might make sense to encapsulate the validation and
untainting of input in a simple object.

Have you looked at CGI::FormBuilder? A quick look at the docs seems to
show that it doesn't automatically untaint input, but it does have a
hook for a validate() method.

I've been playing with a little module for setting up a quick form for
searching a single database table (or view), where each field is an
object, and a form/request is handled by an array of those objects. It's
*very* crude at the moment, as I'm pretty new to OOP, but I may
eventually use it for something real. (at the very least I'm getting
some practice, anyway) If you're interested I can send you a copy --
it's only a few hundred lines.
 
A

A. Sinan Unur

Have you looked at CGI::FormBuilder?

I did but all the HTML stuff is in HTML::Template's and I want to stick
with that. OTOH, I may not be missing something.
I've been playing with a little module for setting up a quick form for
searching a single database table (or view), where each field is an
object, and a form/request is handled by an array of those objects.
It's *very* crude at the moment, as I'm pretty new to OOP, but I may
eventually use it for something real. (at the very least I'm getting
some practice, anyway) If you're interested I can send you a copy --
it's only a few hundred lines.

I would appreciate that actually. I am afraid I can't figure out from the
description above exactly what you are doing and how and it would be
useful for me to see it.

If de-munging my email address below causes problems, you might want to
try:

perl -e "print pack q{H*}, q{73696e616e40756e75722e636f6d}"

Thank you.

Sinan.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,156
Messages
2,570,878
Members
47,413
Latest member
KeiraLight

Latest Threads

Top