Blog posts tagged "webdev"

Session “Flash” in PHP

December 7th, 2005

Doing some PHP hacking tonight, I was missing Rails’ “flash”. So I coded up a quick and dirty implementation of the read-once session status notification pattern. The code

Tagged: Uncategorized , , , ,

OO::Form, initial release

November 24th, 2003

Several months ago, inspired as I recall by Kate’s How to Avoid Writing Code article, I started playing with Class::DBI and Template Toolkit as a rapid development environment.

Not So Fast

Turns out rapid development isn’t really my style. I’m still futzing around with the earliest stages of functionality of my first app I started developing in this brave new way. Part of the problem is I get distracted into “doing things right”, which is about as antithetical to RAD as one can get. I’ve fallen into a number of these sorts of traps on this project, but a major one was the lack of a form class that integrated nicely into this dev. environment. After all you can’t really say you’re doing rapid web development, and then hand build, and process every form, can you?

A Better Params Trap

CGI::FormBuilder is the current standard, and its very impressive in its way, but it didn’t meet my needs. In particular it does too much, and therefore plays poorly with other technologies. It was also totally unsubclassable.

So with great pleasure I present OO::Form 0.01-alpha-experimental. (which has been kicking around for a week fews, but I finally added some POD)

A Curiosity

I don’t really expect anyone to want to use this code yet, but if you’re curious, and/or want to tell me what I’m doing wrong, take a look at it. It is currently incomplete as I’ve been fleshing out the features as needed, but what is in place, is working well (everything documented is working). Also if you’re really interested I’ll send you the code I’m working on that uses it, so you can see it in action. (beyond the example in the POD below)

My Favorite Feature

Besides being all cool, and OO, and integrating well with Class::DBI, and TT2 (and presumably any other template system, but I wouldn’t know), OO::Form allows you to define arbitrary field types. So besides text, password, select, checkbox, and textarea (I’ve been adding the standards as I need them), OO::Form also ships with an OO::Form::Field::date, which does intelligent date, and timezone handling, and while currently displayed as 3 pull down menus, could be easily subclassed (just override the ashtml method) to display via a totally different widget.

OO::Form – pod2html


NAME

OO::Form – an object oriented framework for building, displaying, and processing forms.


SYNOPSIS

package MyApp::AddWidgetForm;

use base ‘OO::Form';

  our $FIELDPROFILE = {
          fields  => 
                  [qw(name widgetstyle note expirationdate) ],
          types   => { 
                  widgetstyle     => 'select', 
                  note             => 'textarea', 
                  expirationdate  => 'date'
          },
          options  => {
                  widgetstyle     => [qw(blue green chrome)]
          },
          required  => [qw(name widgetstyle)]
  };
  sub new {
          my $class = shift;
          my $self = $class->SUPER::new(@);
          $self->addfields($FIELDPROFILE);
          $self->submitfield('addwidget');
          return $self;
  }

….

  (else where in your application)
  my $form = MyApp::AddWidgetForm->new({query => $query, ...});
  if ($form->issubmitted and $form->validates ) {
          MyAdd::Widget->newwidget({
                  name => $form->name->value,
                  widgetstyle => $form->widgetstyle->value,
                  note => $form->note->value,
                  expiration-date => $form->expirationdate->value
}); display
widgetaddedconfirmation(); } else { # form hasn't been submitted, or we encountered an error displaypage($template, { form => $form } ); }

…,

  (mean while, in a nearby template)
  [% IF form.errors %]
  <ul class="errors">
    [% FOREACH e = form.errors %]<li>[% e %]</li>[% END %]
  </ul>
  [% END %]
  Name:       [% form.name.html(size => '40') %]<br />
  Style:      [% form.widgetstyle.html(default => 'blue') %] <br />
  Expiration: [% form.expirationdate.html %]
  Note: <br />
  [% form.note.html(rows =>4, cols=>50) %]<br />
  <input type="submit" name="[%form.submitfield%]" value="Add Widget" />               

...,


DESCRIPTION

OO::Form represents an HTML form as a collection of OO::Form::Field objects, a state (is submitted), and some basic error handling. It was inspired by CGI::FormBuilder, and by the difficulty I had integrating CGI::FormBuilder into my application. The OO::Form was designed to be used in conjuction with the Template Toolkit, and Class::DBI though they aren’t tightly coupled.

The most straightforward way to use OO::Form is to create your own subclass of OO::Form for each form in your application. (though create and update pages can usually re-use the same form object, and for very simple forms, it is probably less useful)

Then pass a ‘fields profile’ to the OO::Form->addfields() method which is a factory method for creating object of type OO::Form::Field and its varied subclasses.


USAGE

Field Profile

A field profile is a compact form of specifying all the fields in your form. (Alternately you could insantiate OO::Form:Field::* objects one by one and add each one with $form->field($field))

A field profile is a hashref with 6 fields.

  • fields
  • An arrayref of the names of fields to instantiate. Names must be unique, and they must not have the same name as any method of your form object (as they will be accessed by calling $form->$field
    name())

  • types
  • A hashref of names mapped to their field types. Any field which is not given a type will be a generic field object, and will be drawn as a text field if their html() method is called.

    OO::Form::Field-factory()> will be called for each field, and be passed its type. The default factory() method tries to instantiate an object of type OO::Form::Field::$type. You can subclass OO::Form::Field to provide a whole set of new field types, or new behaviour for old field types. Additionally if anyone has suggestions for a smarter factory method, I’m interested.

    Current types are the basic HTML fields: text, password, checkbox, textarea, select

    Also the composite field type: date (represented as 3 pulldowns) is available.

    See OO::Form::Field for more detail

  • options
  • For field types with options (selects aka pulldown menus, and radio/checkbox groups) values can be passed with the options field.

    A hashref of field names pointing to either an arrayref of options (when you want value and text to be the same) or a hashref of value to text mappings.

  • values
  • A hashref of field name to value mappings. If you want your field to start preconfigured with certain values, pass in a values hash.

    If your values hashref contains a subclass of Class::Accessor (like a Class::DBI object) then the objects get() method will be called, allowing forms to be rapidly populated from a database.

  • required
  • An arrayref of names of the required fields. OO::Form-validate> will return false (and populate an errors array) if any required fields are missing

2 Error Handling and Validation

There are hooks for a future implementation of a full blown validation framework (probably using Data::FormValidator).

In the meantime OO::Form checks that required fields have been filled in, and that none of the various fields through their own error.

Calling the instance method validate() (validates() is a synonym), returns true or false depending on whether there are any error conditions in the current form. It also populates and errors array, useful for re-displaying the form page with a list of errors.

A useful idiom for calling validates in demonstrated in the synops.

Besides the form wide errors array (accessible at $form->errors() ), each field can have their own error (though only one) accessible at $form->widgetstyle->error(), this is useful for re-displaying a form, with error messages inlined.


METHODS

OO::Form is pretty straightforward, much of the complexity is actually in OO::Form::Field. Almost all OO::Form methods accept a hashref of named arguments.

Note this is all experimental.

  • new($params)
  • Construct a new form. Often you’ll want to override this with your own constructor. The default constructor looks for (and will supply defaults if it doesn’t find): query'',submit
    field”, “time_zone”.

    * query is a CGI.pm object, or something else which masquerades as one

    * submitfield is the name of the button that submits this form (checked by issubmitted.

    * time_zone is used by OO::Form::Field::date to do intelligent localization of date/time values

    Additionally in the future OO::Form::new should take a locale.

  • addfields($fieldprofile)
  • Take a field profile (as discussed in the previous section) an populate a form.

  • field(...)
  • A field accessor. Can take a hashref (or field object) and passes it to OO::Form::Field-factory()>, and attach the results to the current form.

    Otherwise assume a string was passed in, and return the field with that name. (AUTOLOAD will call field($field_name) for unknown methods)

Tagged: Uncategorized , , ,

Web Development with Perl.

September 10th, 2002

In preparation for doing the Protest.net re-write I’m doing some research on web frameworks. I find myself rewriting the same central dispatcher code, adding refinements, like a redirect method (similiar to the forward() method in servlets) and in general missing some of the refinements of Java’s web environments (servlets, Struts, bundles for i18n) while refusing to give up Perl, CPAN, and Template Toolkit.

This is my brain dump so far. Lots of questions, a few answers. The next step will be firing up the text editor and looking under the hood.

Steal from the Best

Applications I’m going to examine for ideas to steal, particularily framework ideas (error handling, inner loop, etc.)

  • Moveable Type – in my few glaces at the code its seemed intelligent, and well structured. Runs under mod_perl and CGI, handles some complex UI demands like pages that use redirects to update progress bars, and re-entrant forms.
  • Bricolage – based on Mason, I’ve been hearing good things about this CMS, particular about its clever Burners abstraction, hope to find other good things under the hood. Don’t really know much about Mason, not sure if that is going to be barrier
  • RT – popular, mod_perl and Mason, ticket tracking software. Also supports email, and command line interfaces.
  • Scoop – haven’t looked at Scoop in a while, but I remember it seemed well done (having just come from looking at Slashcode 1.0), I wonder if it will stand the test of time. Not expecting to find anything all that relevant, but maybe. Will probably do a quick skim of the CMS parade: Slash, Everything2, and maybe LiveJournal. Definitely want to look at LiveJournal’s embedding instructions.
  • ?? Do you any Perl web applications you would consider examples of best practices??

Perl Frameworks

  • OpenInteract seems popular, and uses TT2, but leaves me cold, partially because I’m just not crazy about persistence layers. But I should probably spend some time looking at it. ?? Any expirences using it ??
  • Mason natively uses an embedded, page based execution model, which seems PHP-like to me, but Design Issues with Mason: What are Components For? seems to be simple guidelines for avoiding the siren calls. There is an Oreilly book coming out on it, which will be available online, but the author says, don’t expect it until mid-October.
  • Wombat is billed as an implementation of the Servlet API in Perl, but I can find exactly zero reference to anyone using it, never a good sign.
  • AxKit is a web framework built along the lines of Cocoon. I bet there are seriously cool ideas to steal in there, but I’ve been burned pretty badly playing with XSLT and don’t want to go back into that water right now.
  • OpenFrame also seems interesting. It has the request and response objects ala servlets, and acme is being paid to work on it, and it has a “Slot” concept which seems similiar to Brico’s Burner concept, and supports TT2. However it bills itself as an “open source application framework for distributed media applications.” Which isn’t really what we are building.
  • A few others are listed at Application Servers and Toolkits based on modperl. Also, Web Frameworks and their Template Engines is interesting.
  • Last time I was looking at this stuff there was JellyBean, which no longer seems maintained, and Iadio, which no longer exists.
  • I found a simple home-rolled framework that feels simliar to the one I did for Rockwood. It was mentioned in this interesting thread.
  • The book, Perl for the Web from New Riders, is freely available online and seems interesting if out of date.

Piecemealing with Modules

UPDATE: After looking at the available options, and at Struts 1.1, I would go with Java if I didn’t know I would have an insurrection on my hands.

Tagged: Uncategorized , , , , , ,