The following is a form generator in the vein of Html_Quickform. It'll generate a HTML form and also contains the rules to validate each field and provide you with the validation results.

The idea is that every form field is encapsulated with an object, and each of those objects has a validation rule defining the bounds of the field data. That the actual HTML is encapsulated too just saves on typing out the same thing over and over.

The validation method creates an array keyed by the form field names containing the results of the validation as either true (passed) or false(failed). Error messages can then be displayed based on the array, or in the case of no errors, process the form for whatever purpose.

The code was also my first attempt at Test Led Development. I didn't really follow the paradigm too well (smelly code!) but I really recommend SimpleTest to people interested in this area. TLD really makes you think about your design in the incubating stages of development, and also gives you a safety net when it comes to making changes which possibly have far reaching effects. The set of tests for the classes can be found in the tests folder - you'll need to have SimpleTest installed and in your include_path.

An example form built with this class would be something like this:

$form = new HtmlForm;
$form->setMethod( 'post' );
$form->setAction( '/index.php' );
$form->addField( 'username', new TextField( 'username', '', new SimpleValidationRule( true, '/[a-z]+/', 25 ), 'class="text"'));
$form->addField( 'password', new PasswordField( 'password', '', new PasswordPolicyRule( true, '/[a-z0-9]+/', 12 ), 'class="text"'));
$form->addField( 'submit', new SubmitField( 'submit', 'Submit', new SimpleValidationRule( true, '/[a-z]+/', false ), 'class="submit"'));
if( isset( $_POST['submit'] ))
{
	$form->validate();
	if( $form->hasErrors() )
	{
		// Display errors in $form->getErrors();
	}
	else
	{
		// Do whatever
	}
}
// Display the form
$form->getFormTag();
// PHP 5-only method calling
$form->getField( 'username' )->render();
$form->getField( 'password' )->render();
$form->getField( 'submit' )->render();
$form->getFormCloseTag();

    just had a quick look

    the input fields are not xhtml

    what about implementing $form->submitted() ?
    checking $_SERVER['REQUEST_METHOD' isn't neccessary as well, as you already specified the request method via $form->setMethod

    i'm missing min and max length parameters as well as labels which are quite useful in forms (should be in constructor for form elements imho)

    the possibility to define dependencies would be great (e.g. have $form->validate() check that $POST['new_pass_verification'] contains the same value as $POST['new_pass'] and is different from $_POST['old_pass'])

    aside of this: seems quite good 🙂

      Thanks for the feedback.

      I was tempted to add a flag for XHTML but never got around to it and left the fields as transitional.

      I had a number of problems with determining whether the form was submitted or not. Eventually I just got to the point of adding a session variable - it's an ugly method but I had to get a project finished which made use of this class (lets hope theres not too many bugs eh 😉 )

      Max length is set by the 3rd parameter to the validation rule (this also sets the maxlength attribute for certain fields). Theres nothing for minimum length - good point - although alot of rules can be hacked in using the PCRE pattern (2nd parameter to the validation rule).

      With regard to accessibility features like labels this should be handled by the code laying up the form. Trying to integrate a <fieldset> element into this would be a headache. I'm sure it's possible though.

      With regard to the dependency the idea is to subclass SimpleValidationRule to provide any extra validation features - see PasswordPolicyRule.

        Seems pretty good...what happens if we don't use a class for the form field?

          LoganK wrote:

          Seems pretty good...what happens if we don't use a class for the form field?

          It'll get very angry. You won't like it when it's angry.

            I don't tend to like a lot of things when they're angry...usually that means they're drunk 😃

            Do you know where you PHP script is?

              5 days later

              I've got a suggestion!

              An option to provide client-side validation? When rendering the form itself is rendered it gets an onSubmit handler that calls a validation fnuction. (This function is declared in a <script> block inside the <form> itself so the renderer doesn't have to mess with arbitrary chunks of the page.) I'm thinking that each field with a validation requirement is followed by a short <script> that simply registers another function that returns null or an error message. "Register" just means that it is made known to the form's validation function in some way; when the form's validation function is called, it knows to call each field validator in turn, collecting any error messages (for the benefit of an alert box) as it goes.

                It might be nice to model the class structure in Javascript - your suggestion would lend itself well to that I think. That is create an object with a validate() method to start off with (which simply calls methods belonging to the object). Then as each field is redered a function for that field can be registered with the object, and then the validate() method called onSubmit. Definitely food for thought.

                  Write a Reply...