RE: [PHP] Re: Form handling

[email protected] ("Dajve Green")
Newsgroups php.general
Message-ID <[email protected]>
> -----Original Message-----
> From: Manuel Lemos [mailto:[email protected]]
> Sent: 11 June 2009 07:21
> To: Eddie Drapkin
> Cc: PHP General Mailing List
> Subject: [PHP] Re: Form handling
> 
> Hello,
> 
> on 06/10/2009 03:10 PM Eddie Drapkin said the following:
> > I've been charged with writing a class that handles forms, once they've
> been
> > POSTed to.  The idea of the class is to handle the most common use-cases
> of
> > POST forms, and any special functionality can be handled with a child
> class
> > at a later date, but for our uses, we're going to have mostly pretty
> typical
> > POST forms.  Follows is the list of cases I've determined that are the
> most
> > common, can anyone think of any that are omitted or that are never going
> to
> > be used?
> >
> > class form_handler {
> >     public /* bool */ function setRequiredFields(array $fields); //takes
> a
> > simple array that corresponds to a $_POST key, verifying that there is
> data
> > on required fields but not for optional fields, returns true or false on
> > error
> >     public /* bool */ function setRequiredFieldTypes(array $fieldTypes);
> > //array of field names => type a la ('username' => array(regex,
> > '/a-zA-Z0-9\-_/'))
> >                 //or 'phone_number' => (array('int', 'min_len' => 7,
> > 'max_len' => 10)) etc, the exact spec is obviously nowhere near done but
> > will probably just wrap a lot of filter_ functions, returns true or
> false on
> > error
> >     public /* string */ function validateAndCaptureError(); //returns
> error
> > or empty string
> >     public /* void */ function validateAndForwardTo($page); //forwards
> to
> > page on error, or not
> > }
> >
> > each of the globule setters will have a corresponding appendRequired...
> > method, so as not to require handling enormous data structures for
> > conditional form building.
> > ♦
> > As you can see, the class looks pretty barren, but I can't think of any
> more
> > functionality than would be required, although I am kickign the idea
> around
> > of having very specific validation type methods ie.
> > form_handler::requireInt($field, array $options) or
> > form_handler::requireRegex($field, $regex), etc.
> >
> > Thoughts?
> 
> You may want consider not reinventing the wheel.
> 
> I use this popular forms generation and validation class since about 10
> years now. It can deal with pretty much all you need now and probably
> later.
> 
> http://www.phpclasses.org/formsgeneration
> 
> Here are some live examples of the class and its plug-ins.
> 
> http://www.meta-language.net/forms-examples.html
> 
> --
> 
> Regards,
> Manuel Lemos

Whilst Manuel's Forms Generation class / Zend Form et al are certainly quick and easy to integrate, if this is an in-house project, I don't see a problem with rolling your own Forms class designed to simply automate some of the common functionality your developers use. In a lot of cases, out-of-the-box classes come with bloat while being all things to all men, which is not a bad thing, per se, but needs to be weighed up when selecting a methodology.

To answer your original question, though, our in-house framework has a base Form class, which is extended through child classes, as well as a base input class, which is extended with child classes such as TextInput, SelectInput etc. This allows each input to have its individual validate() methods, as well as creating a wrapper Form::validate() method which loops through the Input::validate() methods.

Example

$Form		= new Form;
$Form->fields['text']	= new TextInput;
$Form->fields['select']	= new SelectInput;
$Form->fields['select']->options	= array('foo' => 'bar', 'wom' => 'bat');

With regard your setRequiredFields(), we use an Input::$mandatory property, which the Input::validate() method checks.
The setRequiredFieldTypes() is dealt with by the actual File class.
I would certainly separate out the required validation as mentioned with requireInt/Regex methods, which would allow combining of required conditions. We use a $validation bitwise property in the Input class combined with class constants, as well as minlength / maxlength properties for text / password fields.

Other things to consider

- Some method of storing user messages during validation which can be output later.

- Creating an output method for the fields. Repopulating the fields with submitted values, using CSS to highlight missing or invalid fields or creating "custom" fields (such as a date input with a calendar / made up of Y/M/D select inputs) can lead to a mess if you are hardcoding the output. 
For example:

$Form->fields['text']->add_css_class('missing_mandatory');
$Form->fields['text']->set_value('Foo');
$Form->fields['text']->output();

Something further to consider would be to have a $value property and use __set() overloading (http://us3.php.net/manual/en/language.oop5.overloading.php) to validate
Eg 
$Form->fields['select']->value = 'foo'; // Sets value to foo
$Form->fields['select']->value = 'No such option'; // Does not set

- A method / property to check whether the form has been submitted.
If you have a Form::id property, you can pass this through in a hidden field and create a method which checks for the presence of this in the $_POST array.
Example

class Form {
  public $id;
  public $form_id_key = 'my_form_id';

  public /* bool */ function has_been_submitted() {
    $submitted = false;
    
    if (array_key_exists($this->form_id_key,$_POST) &&
        $_POST[$this->form_id_key] == $this->id) {
      $submitted = true;
    }
    
    return $submitted;
  }
}

$Form->id = 'myform';
if ($Form->has_been_submitted()) {
  // Process the form
}

[snip]

<form method='post' action=''>
  <input  type = 'hidden' 
          name = '<?php echo $Form->form_id_key ?>' 
          value= '<?php echo $Form->id ?>' />
</form>

It would be worth thinking about how to handle cases where a Form id is null when checking for submission.


Finally, if the class starts out looking barren, that's not a problem - there's always room to expand if more functionality is needed. Filling a class with functionality you might need, without where and when you'll need it, or how you expect to use it is a Bad Thing.


Apologies all for the essay, but hopefully it's of some use.
Dajve

----------------------------------------------------------------------------
for (thoughts, ramblings && doodles) {
  goto http://dajve.co.uk ;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.