A long time ago, I mused about fetching objects directly from HTML forms instead of grabbing the ID, untainting it, validating it, and instantiating a new object. I finally wrote up a proof of concept. You can read about it at Perlmonks. Basically, it lets you do stuff like this:
use Class::CGI handlers => { customer => 'Class::CGI::Customer' }; my $cgi = Class::CGI->new; my $cust = $cgi->param('customer'); my $email = $cgi->param('email'); # validate email $cust->email($email); $cust->save;
Re:I can see your future
Ovid on 2006-04-08T08:01:22
First you'll want to auto-inflate a single param, so you'll do what you have now.
Yup. Got that.
Next, you're going to want to have more than one CGI param for each object. So you can do things like composite dropboxes and so on.
Yup. Added that a few hours ago. It was a simple matter of fixing an egregious design flaw in my original code.
Then you are going to want to define a whole group of these in one hit, so you can have something like Class::CGI::Form, which would extract a whole bunch of fields as a discrete unit.
Nope. My thought is that forms can define the handlers they need:
<input type="hidden" name="__PROFILE__" value="customer"/>
<input type="hidden" name="__PROFILE__" value="date"/>
<input type="hidden" name="__PROFILE__" value="order"/>
<!-- actual form parameters follow -->And in the actual code:
use Class::CGI profiles => 'Some::Profile::Class';
my $cgi = Class::CGI->new;
my $cust = $cgi->param('customer');
my $date = $cgi->param('date');
my $order = $cgi->param('order');Note that those params might not actually exist in the form. Instead, each handler simply knows what to look for to create the appropriate objects. See this post for an example. The end user code does not know or care how the object is actually fetched. The handlers encapsulate what they need to know to get the job done.
Also, the parameter name __PROFILE__ would be the default but it could be overridden.
Then you are going to want to have more than one form on a page.
That's handled by what I listed above.
And finally you are going to be annoyed that a form element may or may not be on the page, so you'll want to make CGI more deterministic.
Again, this is dealt with in each handler. The handler is responsible for knowing how to build the appropriate object, not the calling code. By correctly pushing to the handler the responsibility of gathering the appropriate information, we don't need a lot of funky "configuration" scaffolding or anything like that. It has all of the flexibility to meet what you're listing but without the complexity that other alternatives offer. In fact, the only significant scaffolding we would need is the ability to specify the location of the "profiles" class or file. This would map each handler to the appropriate class.
Yes, I know that sounds arrogant and I feel a little bit awkward by that, but as I've been programming over the years I've discovered that the complexity of well-designed code tends to match the conceptual complexity of an idea. If my conceptually simple idea results in complex code, there's a good chance I have a design flaw. By viewing an HTML form as merely a collection of objects, I can write simple code that reflects this. Simple is good.
As for separators in CGI form parameter names, my code is completely agnostic about that. Again, it's the handler's responsibility.
Re:I can see your future
Alias on 2006-04-08T14:16:30
The one big trouble I see with having the form specification on the page itself is it violates the idea of everything that comes in from CGI being evil.
What if you trust a Class::CGI-instantiated object to be something, and someone just changes the spec on the page...
The other steps I missed after those, is that once you have a Class::CGI::Form-like thing, you'll want to automatically generate those based on things like Class::DBI classes.
And that means to some degree the program itself needs to control what params it is expecting, rather than letting untrusted external people do it.
For example, how do you get your form specification past tainting?
The whole thing becomes tainted...
Re:I can see your future
Ovid on 2006-04-08T16:48:48
First, the __PROFILE__ would be strictly optional. You're always at liberty to declare the handlers in your code instead.
Second, I agree with what you're saying about a security hole. I should add a signature check if profiles are listed in the HTML.
Re:I can see your future
Ovid on 2006-04-08T19:23:07
In thinking about this more, I see that the benefits of having forms declare which handlers they need are outweighed by the security issues. I'm pursuaded enough by your arguments that I think I'll abandon __PROFILE__ declarations in the HTML. Thanks for kicking me.
Re:I can see your future
Alias on 2006-04-09T03:39:05
Ironically, there does exist an analogue of what you describe.
It's called XForms:)
But in the case of XForms, it's able to leverage Schema validation to deal with it's evil problem.