views:

560

answers:

3

I'm been a PHP developer for quite some time now but until today I've not found a simple way to process (aka normalize, sanitize, validate, populate and display forms and it's respective field errors).

I know that most of the PHP frameworks nowadays make this job easier but somehow I don't feel like porting all my code to one of these frameworks, and I can't quite understand how the form validation is implemented in Django for instance (I know, it's Python but I really like their approach), so I though the best way would for me to post here the way I process a simple form and maybe you guys can point me in the best direction.

<?php

// sample controller
class _sample extends framework
{
    // sample action
    function contact()
    {
     if ($this->Is->Post() === true)
     {
      $errors = array();

      if ($this->Is->Set($_POST['name']) === false)
      {
       $errors['name'] = 'Please fill in your name.';
      }

      if (($this->Is->Email($_POST['email']) === false) || ($this->Is->Set($_POST['email']) === false))
      {
       $errors['email'] = 'Please fill in your email address.';
      }

      if (($this->Is->Phone($_POST['contact']) === false) && ($this->Is->Mobile($_POST['contact']) === false))
      {
       $errors['contact'] = 'Please fill in your phone (or cell phone) number.';
      }

      if ($this->Is->Set($_POST['message']) === false)
      {
       $errors['message'] = 'Please type a message';
      }

      // no errors, it's valid!
      if (empty($errors) === true)
      {
       // do stuff and redirect to "success" / "thank you" page
      }

      // load the form view, and let it display the errors
      // automatically prefill fields with $_POST values
      else
      {
       $this->View('contact_form', $errors);
      }
     }

     // load the form view for the first time
     else
     {
      $this->View('contact_form');
     }
    }
}

?>

As you can see, this is supposed to be a simple contact form however it takes the life out of me to validate it, I have been looking into some design patterns (Observer, Factory) but I do not feel confident if and in what way I should implement them.

+1  A: 

I know it's something you excluded, and me too was like you up until a year ago, when I forced myself to learn something obscure like Qcodo (php framework), and lo and behold, I can't do anything without it noways. It's simply wonderful to take off lots of always repeating burden off your shoulders. Why Qcodo? At that time I wanted to learn the most advanced one since I'm already learning, so I looked for the most broad feature set, which Qcodo seemed to offer. Today I don't know which one is the hottest, but for me Qcodo is still fulfilling all my needs.

Mark
+2  A: 

IMHO, the attempt to treat a form as a single concept is a failure. If you have any kind of layered architecture to your application, forms are likely to cut across these. Forms have application logic (controller layer), they have a visual representation (view layer), they have state (application layer model), and in the end they usually invoke some kind of transactional script (model layer).

I think you're much better off dropping the idea of a "form" as an entity and instead focus on the three parts (input processing, rendering and model layer) as completely separate matters, that just might (or might not) happen to be closely related to each other. This is some times referred to as the MVC pattern, although the term is so strongly loaded by now that it could mean a lot of things.

troelskn
+1  A: 

You could make an abstract base class for all your forms, classes for fieldtypes, and a static class just for validating the values of various types (validateString, validateHtml, validateEmail, validateNumber, date, etc, just the methods..). Defining your form, you would define what field objects would it use, so the Form->validate() method would invoke the Field->validate() and return the filtered value or error message. Specify default error messages for the fields, but give an option to override it when defining fields in your form class.

Oh, and leave that $_POST thing. Read the post once, pass it once to the form validation and then work on filtered field values.

Another thing is there are various ways to achieve form validation depending on your needs and the architecture of your applications, it can be hard to make an all-purpose form validator when you have various approaches to your application design. Choose a way of doing your work and stick to it (regardless if it's a ready to go framework or your own code), or whatever super-duper-form-validation you write, it will make no sense in latter projects.

One more: like Django? Good! So start programming Python in Django, you'll really change the way of thinking how to get your job done.

zalew
JZ, I like the way you are thinking, could you please elaborate a bit more?Specifically, would this Form object be the same used for displaying and validating forms? How could I accomplish multiple alternative validations like the $_POST['contact'] field above?Thanks.
Alix Axel
Yes, a module that renders the form and validates it. That is why I mentioned the fact, that much depends on the design of your whole application, the way you implement the MVC pattern as troelskn mentioned above, etc. However, you can make a class for validation data only if that's all you want.
zalew
[continued] I just don't think making a validation-only class will get you closer to the django way you mentioned in your question, the validation there is so sweet because it's part of a whole well designed form processing.
zalew