SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 46

Thread: Forms, fields, filters (looking for input)

  1. #1
    SitePoint Wizard Chris82's Avatar
    Join Date
    Mar 2002
    Location
    Osnabrück
    Posts
    1,003
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Forms, fields, filters (looking for input)

    Hello,

    I had some time and continued to work on an approach for creating forms. Several ideas and code used are from Vincent's replies in my first thread about this. Additionally, it also uses the functionality of his ECLIPSE class libary.
    The idea of Filters mentioned in the thread about PEAR::QuickForm made me move the error checking from each field to separate filter classes.

    I currently have the following structure:

    A class Form which holds references to FormComponents in an array.
    FormComponent is the superclass for all fields. Subclasses are TextField, TextArea and PasswordField.
    Each field has a basic filter that checks if input is required for the field or not. Subclasses of this Filter are for example EmailFilter which checks the validity of an email adress and can be applied for a field.
    Currently, a FormComponent can only use one filter. However, I think that this is sufficient.

    Here is an example for an AddressForm:

    Code:
    <?php
    if (!defined('CLASSROOT'))
    {
    	define ('CLASSROOT', 'classes');
    }
    
    require_once CLASSROOT.'/form/Form.php';
    require_once CLASSROOT.'/form/FieldFactory.php';
    require_once CLASSROOT.'/form/SampleViewer.php';
    require_once CLASSROOT.'/form/Filter.php';
    
    class AddressForm extends Form
    {
    	function AddressForm($method, $action)
    	{
    		parent::Form($method, $action);
    		
    		//               name         type   needed     filter
    		$this->addField('firstname', 'text', true,  new Filter());
    		$this->addField('lastname',  'text', true,  new Filter());
    		$this->addField('address',   'text', true,  new Filter());
    		$this->addField('telephone', 'text', false, new TelephoneFilter());
    		$this->addField('email',     'text', false, new EmailFilter());
    	}
    }
    
    $form =& new AddressForm('post', $_SERVER['PHP_SELF']);
    $form->display(new SampleViewer, $_POST);
    
    if (!$form->submit($_POST))
    {
    	echo '<pre>';
    	echo $form->getErrorMessage();
    	echo '</pre>';
    }
    
    else
    {
    	echo 'success';
    }
    ?>
    I have attached the source files in order to run the example above. However, the source files are not properly commented (ie. there are hardly any comments at all ;-) )
    If you would like to try it out, I think it is best if you extract the files to <apachedir>/htdocs/classes/form. Otherwise the classroot constant in those files needs to be changed. As I use ECLIPSE you would also need it.
    I used Windows, so I don't know if it runs under Linux as well.

    Thanks in advance for any comments,
    Christian
    Attached Files

  2. #2
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am not sure if your class is meant to be a form validator, a form displayer or some sort of combination of both, but I assumed it is meant to abstract validating forms from displaying them. Some comments on the point of re-usability and abstraction:

    - Does it matter to form validation if a field is a textarea, a a password field or a regular textbox? This is merely a way a form component is displayed, it does matter for the value that is submitted back to the script. I think you can abstract classes 'PasswordField', 'TextField' and 'TextAreaField' to one class called 'TextField'. The same can be said for radio buttons or a select box: the way the selected value is submitted is the same, only the way these elements are displayed (which you'd want to abstract / not care about) varies.

    - A field should not be limited to just one Filter. By having multiple filter objects on one Field, you can achieve something like checking for the length of a field while also checking if all its characters match a regular expression. I know these two can be combined into one regular expression, but a solution with multiple filters seems more flexible to me, also when it comes to giving user-friendly error messages.

    - The $action parameter you pass to the Form is in my opinion more a 'form display' concept than a form validation concept.

    - Right now you have a method getErrorMessage which, assumingly, returns one error message for the form. It is helpful for users of the forms if they see all error messages at once instead of only one at a time.

    - You use $form->display($sampleViewer) which in essence couples the form validator and the form displayer classes, which is not necessary. Perhaps something like this would be better and lead to less dependencies in the code:

    PHP Code:
    $formValidator = new AddressForm;
    $view = new SampleFormView($formValidator); 
    I hope you find these comments useful

  3. #3
    SitePoint Wizard Chris82's Avatar
    Join Date
    Mar 2002
    Location
    Osnabrück
    Posts
    1,003
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am not sure if your class is meant to be a form validator, a form displayer or some sort of combination of both, but I assumed it is meant to abstract validating forms from displaying them.
    I actually thought of it as a form displayer. I don't use a validator for the whole form just for the fields.

    - Does it matter to form validation if a field is a textarea, a a password field or a regular textbox? This is merely a way a form component is displayed, it does matter for the value that is submitted back to the script. [...]
    You mean like adding a new member $type to a class TextComponent which is used when the field is displayed?

    Code:
    echo '<input type="', $this->type, '...>';
    I think this is a good idea.

    - A field should not be limited to just one Filter. ...]
    I will see how easy it is to implement multiple filters for the fields. Probably using an array which stores the filters.
    Before I forget my idea:

    Code:
    // in class FormComponent
    $valid = true;
    for ($it = new ArrayIterator($this->filters); $it->isValid(); $it->next)
    {
        $filter =& $it->getCurrent();
        $valid = $filter->isValid($this);
    }
    
    return $valid;
    - The $action parameter you pass to the Form is in my opinion more a 'form display' concept than a form validation concept.
    As mentioned before, I thought of the class as a form displayer and not as a validator.

    - Right now you have a method getErrorMessage which, assumingly, returns one error message for the form. It is helpful for users of the forms if they see all error messages at once instead of only one at a time.
    The error message includes every error (missing or invalid data). I am also not very happy with the way it is done currently, because I have the error messages hardcoded in the form class. I thought about placing more descriptive error message in the Filter classes in case a field is not valid.

    I hope you find these comments useful
    Yes, they are very much appreciated.

  4. #4
    SitePoint Enthusiast
    Join Date
    Jan 2003
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    keep this up

    Hey, keep this up, this is great! This could be a nice replacement for quickform. I know to Sork also mentioned that he was working on a form class + formrules class. Perhaps we could all get in on this thread and work to something solid.

  5. #5
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, if this is more a form displayer like you say, you should not be mixing in form rules with this. That is precisely what is wrong with QuickForm: it mixes validation logic with form displaying.

    If you really want this to be different from QuickForm, you should focus on separating these two.

    You mean like adding a new member $type to a class TextComponent which is used when the field is displayed?
    Not really, the example you showed would not work for <textarea> tags by the way. What I meant was only useful if you were creating a form validator, which I thought.

  6. #6
    SitePoint Wizard Chris82's Avatar
    Join Date
    Mar 2002
    Location
    Osnabrück
    Posts
    1,003
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, if this is more a form displayer like you say, you should not be mixing in form rules with this. That is precisely what is wrong with QuickForm: it mixes validation logic with form displaying.
    You are probably talking about the method 'submit' which mixes validation into the presentation?

    Maybe another approach:

    PHP Code:
    $form =& new AddressForm('post''foo.php');
    $form->display(new SampleViewer$_POST);

    $validator =& new FormValidator($form);
    if (
    $validator->isValid())
    {
        
    // do something

    A bit different from the way you posted before.
    However, what would the Validator class do? I think it would only loop through the fields of class Form. Basically the functionality of 'submit' from class Form moved into a separate class. The FormValidator validates each field of the form by using the filter(s) applied to that field.

    PHP Code:
    class Validator
    {
        var 
    $form;

        function 
    Validator(&$form)
        {
            
    $this->form =& $form;
        }

        function 
    isValid()
        {
            
    // loop through the fields
        
    }

    And one more question. Where should the error messages go? I mentioned before that I thought of moving error messages to the Filters in case of an invalid field. Is it a good idea?

    @mojavelinux: Thanks for your comments.

  7. #7
    SitePoint Zealot Sork's Avatar
    Join Date
    Jul 2002
    Location
    Portugal
    Posts
    143
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This is just theory
    I don't understand how we validate the data sent by the form, have we to rebuild the entire form in the other (virtual)page to know what fields and rules are avaiable?

    An idea of doing it?
    PHP Code:
    $form =& new FormObj($name$bla,$bla);
    $myField =& $form->addElement(new TextElement('myField'));
    $myField->addfilter('a_filter');
    ...
    //get the elements
    $formAr =& $form->getElements();
    //display it 
    ... 
    The addFilter() call another class, FilterObj, that adds the filter to the element in a array. This class serializes the object and then in other page unserializes the object and run a
    PHP Code:
    $vForm->validate(); 
    I don't know if this is the way of acomplish it, just an idea!
    What's your opinion?

  8. #8
    SitePoint Wizard Chris82's Avatar
    Join Date
    Mar 2002
    Location
    Osnabrück
    Posts
    1,003
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Sork,

    Thanks for your input.
    I do it almost exactly like you. I add fields with filters to the form. The displaying is done with a method inside class Form using Vincent's Loop::run(...) method.
    At first, I also had a validate method in class Form (submit), however as Captain Proton pointed out it mixes validation with displaying and I thought about moving it to a special class called Validator.

    Your point about rebuilding the form made me aware of another problem
    I currently only used the same page to display and validate the form. I have never really used serialization but does PHP also serialize objects within objects (as it needs to be with the fields and their filters).

    Code:
    // page input.php
    $form->display(new SampleViewer, $_POST);
    Code:
    // page process.php
    
    // here we need to get the original form back for the 
    // validation 
    
    $validator =& new Validator($rebuildForm);
    
    if (!$validator->isValid())
    {
       // send the user back to the input page
       // however, will the user input be still there?
       header ('Location: ....');
    }
    I will look into serizalize() and unserialize().

    Thanks,
    Christian

  9. #9
    SitePoint Enthusiast
    Join Date
    Jan 2003
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    composition

    Okay, we have a few questions going on here, but we will get through them. Let's look at the first issue of a class trying to "do it all." I bet I know what Vincent would suggest (but I am not him, so these are my words). COMPOSITION. The form object is created. At this point it can be used as is, with no special hooks or validation, for someone looking to create a simple form. No bloat.

    Now, comes along a user who wants form validation. So we instantiate a FormValidator class (as was mentioned a few posts up) and we pass in the form object. Composition at it's finest! Now, we can add Rules and Filters to the validator (which themselves will be other object instances), so MORE composition. Whoohoo!

    Okay, now when I talk about form validation, I was referring 100% to javascript. Having that type of validation would not cause a problem with rebuilding the form to validation since it is done on the same page. The problem comes when we want server side validation of the form.

    I believe that server side validation is a whole other ballgame from forms. It deals with the objects the form creates and each of those DataObjects should probably access a different Validation object, such as DataValidation with its own rules and filters. I could be wrong, but it seems as though validation for typing in a form and validation for the resulting post data are two different things. However, I am open to all views on this, that is just to get you thinking a bit.

  10. #10
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So we instantiate a FormValidator class (as was mentioned a few posts up) and we pass in the form object. Composition at it's finest!
    No, no, no.. Composition maybe, but this is not proper layering of code at all! A form validator object should have nothing to do with the way a form is being displayed.

    As an example of what I'm trying to say, let me show you some code I am developing myself:

    PHP Code:
    $formValidator = new FormValidator($_POST);
    $formValidator->addField('text''username''Username', array(
        new 
    LengthFilter(620),
        new 
    RegexpFilter('/^[a-zA-Z]+$/')
    ));
    $formValidator->addField('singlechoice''admin''Administrator Privileges');
    $formValidator->addField('text''email''E-mailaddress', array(
        new 
    EmailValidator
    ));

    /* Validate the form on the server-side */
    if ($formValidator->isValid())
    {
      
    // Process the validated submission of the form
    }

    /* Pass the FormValidator to some sort of object in the 'presentation' layer */
    $formView = new MyFormView($formValidator); 
    PHP Code:
    /**
    * This class builds a HTML page with a <form> object in it
    *
    * It [b]USEs[/b] the FormValidator to get some javascript code for client-side
    * and to display the error messages
    **/
    class MyFormView
    {
      function MyFormView($formValidator)
      {
        // Just for example's sake I am echoing HTML directly here
        ?>
        There were some errors while submitting the form:
           <?php foreach($formValidator->getErrorMessages() as $errorMessage) { ?>
           - <?=$errorMessage?>
           <?php ?>
            
        <form action="/mysite.php" method="POST">
            Username: <input type="text" name="username"><br>
            E-mailaddress: <input type="text" name="email"><br>
            
            /*
            * I am using a group of radio buttons here, but I could also use a <select> drop down
            * The FormValidator object does not care about this, because select boxes and radio buttons
            * will give the same kind of value in the $_POST array.
            * This is how the presentation of the form and validation of the form are decoupled
            */
            Administrator: <input type="radio" name="admin" value="1"> Yes
                                <input type="radio" name="admin" value="0"> No
            
            // I could also have done this:
            <select name="radio">
                <option value="Y">Yes</option>
                <option value="N">No</option>
            </select>
            
            <script language="JavaScript">
                <?=$formValidator->getJavaScript()?>
            </script>
        </form>
        <?php
        
    }
    }
    This is just an example of course, but I believe it demonstrates some good techniques:

    - MyFormView depends on the FormValidator, but the FormValidator does not in any way depend on MyFormView. This means that FormValidator is a layer below MyFormView. And if you read Vincent's posts correctly, layering is one of the true powers of OOP one would want to achieve.
    - FormValidator does not care about the presentation of the form; it does not care if a 'single choice' type of field is a set of radio buttons or a select box. The same goes for textboxes, textareas and password fields. This is again an example of decoupling of presentation from the layers below it.

  11. #11
    SitePoint Enthusiast
    Join Date
    Jan 2003
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    correction on my post

    Oh, I wasn't saying that the FormValidator would display the form, what I was saying is that you pass in the form object so that the FormValidator can construct javascript that relateds to that form (you pass in the object so that you can get information from it, not to write to it). But I believe I am still on my way to layering because you also then need a FormDisplay class or FormLoop that loops through the form and display it (just like Vincent has a BookPrinter)...oh, okay FormPrinter object.

    Note: Again, I am not an expert, I am trying to get this as best I can. I am listening with all ears Captain Proton. I believe that if I keep probing at a solution here I can grasp this concept, so don't ever hesitate to correct, but do know that I, like many here, are trying our very best to understand the OO concepts. I am going out tonight to buy the books Vincent recommended and I will never cease learning about this as I know even Vincent still has answers to fill.

  12. #12
    SitePoint Wizard Chris82's Avatar
    Join Date
    Mar 2002
    Location
    Osnabrück
    Posts
    1,003
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Your FormValidator class I think is a mixture of parts of my Form class and a separate Validator.
    Your addField() method I think is a factory. The Validators you pass in the constructor where are those stored and do you create some kind of Field object?

    However, don't you basically have to do similar tasks twice? (judging from the code you posted)
    Add the fields to FormValidator and hardcode the html for the form in MyFormView.
    Or do you use the fields stored inside the Validator to generate the html?

  13. #13
    SitePoint Enthusiast
    Join Date
    Jan 2003
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The FormPrinter should take a Form and a Validator (or maybe extended so that a form printer can exist without a validator) and will match up the two. But really, why does the form need to know about the validator at all? When the form is passed into the validator, the validator tacks on an onSubmit="validateForm()" or something and then when the form is printed, it doesn't have to know about the validator.

    Of course, this is all assuming we don't have some strange browser quirk to get around. Again, I am brainstorming, but like Captain Proton said, we need to make sure that each object does only what it is supposed to do and not try to do another object's task. When you are adding form validation rules, yes you are talking about the same form field a second time, but that is the same as you would do anyway. First you create the element. Second you, optionally, add a validation rule to it. This way, when you cycle the page around and recieve the form input, you only have to play with the validation rules and not with the form elements.

  14. #14
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    However, don't you basically have to do similar tasks twice? (judging from the code you posted)
    Add the fields to FormValidator and hardcode the html for the form in MyFormView.
    Or do you use the fields stored inside the Validator to generate the html?
    That's right, I have to do similar tasks twice. But this is because I want to abstract my form validation from the displaying of the form. Like I said in one of my previous posts, it does not matter to the code that validates a form if a text field is a textbox, a textarea or a password field. The logic in the form displayer that chooses the type of text field to display (textbox, textarea, etc) is logic that has nothing to do with validating the form, so it should IMHO not be mixed. I don't actually harcode the HTML for form elements, but that is besides the point. There is a difference between the concept of a 'form validation field' and a 'form display field'. The first is about the kind of value that is submitted back from the form, the second about the form widget/control that is presented to the user.

    But really, why does the form need to know about the validator at all? When the form is passed into the validator, the validator tacks on an onSubmit="validateForm()" or something and then when the form is printed, it doesn't have to know about the validator.
    It still needs to present error messages and, assuming you want client-side validation, get some javascript to validate the form. I think the form should get both of these from a form validator.

    Another disadvantage of the approach you present is that you first have to build the form presentation before you can validate it. You may not actually be displaying the form to the user first, but you build it by assigning fields to the form. When a form submission is valid and you for example need to redirect the user to another page, there is no need to build this form since it is not displayed, it's just wasted processing time.

  15. #15
    SitePoint Enthusiast
    Join Date
    Jan 2003
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    clear up

    Another disadvantage of the approach you present is that you first have to build the form presentation before you can validate it.
    I'm not sure which post you are refering to, but if I could clear up something that maybe my post didn't get across. I totally agree that the validator and the form are two seperate entities and that you do not have to build up the form in order to validate the data. Your points are explained very well there and it is certainly something QuickForm does not do.

    Sork and Chris82, I believe the question we need to answer is, can "our" form class just make a form without anything else, no validation or whatever. Once we do that, the role of the form object will be clear. Remember, a clearly defined role is critical for an object. Next we need to think about the form validator and its roles and how they interact, perhaps they interact through a FormPrinter. So if we had to redisplay the form because of invalid data. The FormObject would have the instructions of which elements to create, the FormValidator would contain the errors, and the FormPrinter would know where to place the errors in relation to the form elements. However, if you didn't want to display the form, the FormObject would be unnecessary and perhaps the LogPrinter could work with the FormValidator object to print the errors to a file (who knows, just an example). Captain, am I on track there?

  16. #16
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yep I guess so. If I understand you correctly you want to have a 'FormObject' which contains the definition of the form fields. The form validator uses this object to add filters/rules to these fields and the FormPrinter uses it to determine which display elements it should put in the HTML.

    I think this makes sense for scripts where the display of the form is simple and coded by the programmer: just a set of form fields with labels and such. But imagine if you are working together with a web designer who hardcodes the form display in HTML. IMHO, you need to ask yourself the question "can I still use my form [validator] class(ses) for this approach?". If the answer is yes, you're on the right track

  17. #17
    SitePoint Wizard Chris82's Avatar
    Join Date
    Mar 2002
    Location
    Osnabrück
    Posts
    1,003
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Captain Proton,

    concerning the code you posted: Your form validator would only work for a special form which has three fields: a textfield, a select box / a group of radio
    buttons and another textfield?

    Another question on the Filter / FieldValidator classes: where should they be put? Somehow, these reminded me of EventListeners in Java, which however have a somewhat different purpose. The point is, EventListeners are assigned to buttons which themselves are later added to some panel.

    Code:
    JButton plus = new JButton("+");
    plus.addActionListener(new ActionListener() { .... } ; );
    panel.add(plus);
    Isn't it possible to apply the panel / button part to a form with fields? The panel being the form and the buttons the form fields?

    <edit>However, the final validation should be done in a different class. This way a form has it's own fields with assigned Filters / Validators and the validation could be done in a separate class. I admit, though that the form would still need to be build before any validation can take place.</edit>

    And my final problem is that I like Vincent's idea and implementation of the FormViewer. This would not work anymore if the form did not have single fields.
    Last edited by Chris82; Jan 31, 2003 at 14:51.

  18. #18
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    concerning the code you posted: Your form validator would only work for a special form which has three fields: a textfield, a select box / a group of radio
    buttons and another textfield?
    Well, class FormValidator is a generic form validation class. By using the addField() method, you can define which fields a form has. You can use it for any kind of form. You could implement subclasses of FormValidator that set up the fields for a specific type of form if you want of course.

    And my final problem is that I like Vincent's idea and implementation of the FormViewer. This would not work anymore if the form did not have single fields.
    Not sure I understand what you mean here. And I seem to have lost the link to that thread with the FormViewer idea, could you please post it?

  19. #19
    SitePoint Wizard Chris82's Avatar
    Join Date
    Mar 2002
    Location
    Osnabrück
    Posts
    1,003
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This was the original thread: http://www.sitepointforums.com/showt...threadid=77563

    Basically, the method display() iterated through the fields which were stored in an array inside of class Form.

  20. #20
    SitePoint Zealot Sork's Avatar
    Join Date
    Jul 2002
    Location
    Portugal
    Posts
    143
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was thinking about how the form and the validator should work.

    The form and validation rules are always constant so makes sense we have just to write it once, right?

    And now i want your opinion about this:
    - In the page that the form is created we check if the form isn't already in cache(this cache is the serialized array that FormPrinter receives stored somewhere). If yes we load the form array.

    - In the next page we only have to load the validation rules, check them, and if something goes wrong the form array is loaded.

    some simple examples
    PHP Code:
    /*
    The first page
    */
    $form =& new FormGenerator();
    if (
    $form->isCached())
    {
        
    $formPrinter =& new FormPrinter($form->load());
    }
    else
    {
        
    //Build the form
        //And rules
        
    $formPrinter =& new FormPrinter($form->get());
    }

    /*
    The second page
    */
    $validator =& new FormValidator();
    $validator->load();
    if (
    $validator->isValid())
    {
        
    header('location:');
    }
    else
    {
        
    $form =& new FormGenerator();
        
    $formPrinter =& new FormPrinter($form->load());

    This is good or am i out of track?

  21. #21
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You're making two assumptions that are incorrect, I believe:

    - validation rules are not always constant, they can depend on the submitted form values. Imagine a form for editing a user account with two optional fields to change the user's password, one for the password and one to confirm it. The confirm password field is only required if the password field is filled in.

    Another example could be some sort of application form, where the format of a postal code / zip code depends on the selected country.

    - you cannot depend on there being a serialized version of a form somewhere. It is possible that somebody creates a copy of your form HTML, puts it on some other site and has it submit to your script. Where do you get your serialized form from then?

  22. #22
    SitePoint Zealot Sork's Avatar
    Join Date
    Jul 2002
    Location
    Portugal
    Posts
    143
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah! i get you!

    But your second point is irrelevant for what i was trying to do, because someone could always do that.

  23. #23
    SitePoint Wizard Chris82's Avatar
    Join Date
    Mar 2002
    Location
    Osnabrück
    Posts
    1,003
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    - validation rules are not always constant, they can depend on the submitted form values. Imagine a form for editing a user account with two optional fields to change the user's password, one for the password and one to confirm it. The confirm password field is only required if the password field is filled in.
    This is another possibility that does not work with the current version of my Form class.
    It really adds additional complexity to form validation. I tried to come up with some pseudo code and it prooves to be quite difficult and it also means that I have to rewrite and drop some ways my classes currently work ...

    Should these dependencies best be added to the fields in the FormValidator?

    PHP Code:
    // first approach that came to my mind

    // in class FormValidator
    function link($field1$field2)
    {
       
    // don't know if this actually works
       
    $this->fields[$field1->getName()]->setDependency($field2);
    }

    // then how to validate it
    function isValid()
    {
       
    // in a loop
       
       
    if ($field->hasDependency())
       {
          
    // assuming a field can only have one dependency for 
          // simplicity

          
    $dependency =& $field->getDependency();
       
          
    // assuming further that this field has a Rule which
          // says that the input of both fields must be equal
          // now how to do it?
          // maybe a static method which returns true / false?
       
          
    $this->valid Comparator::compare($field$dependency);
       }

    Or another option:

    PHP Code:
                         'name' 'type''text',     'required'
    $field1 =& new Field('pw',  'text''Password'true);
    $field2 =& new Field('cpw''text''confirm',  true);

    $field1->addFilter(new PasswordFilter(48));
    $field->setDependecy($field2);

    $validator =& new Validator($_POST);
    $validator->addField($field1);
    $validator->addField($field2); 
    Maybe I should extend from FormValidator and create a subclass such as SignInValidator which creates the necessary fields.

    What kind of dependencies exist between form fields?

    - equal input
    - input only required if another field has been filled out / selected (as your password example)
    - similar to the 2. input that is valid only for a certain option (as your zip code example)

    This leads to another question: Can you include solutions for every single possibility a user can think of or is it better to write something that is useful, solves a common problem really well but can be used (extended) to match the users requirements?

  24. #24
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think that these dependencies between form fields can become very complex, for example a field only being required when field A is filled in and the value of field B = 'Yes' or something like that. I don't think there's a way you can develop classes for every possibility.

    You could include a method in your form class that is called to set these dependencies. Subclasses would then implement this method.

    Also, here's some explanation about types of form validation, it may be helpful to you. There are essentially three types of validation that come into play with form validation:
    - syntactic validation
    This is validation that works on a single field and it checks the 'format' of that field. Examples could be checking if a field has a valid e-mailaddress, the value is long enough, is a valid date, etc. I think it is possible to create classes for most types of this validation.

    - semantic validation
    This is validation that operates on multiple fields. Examples include checking if two fields match, a field that is required when another one is filled in. Since the semantic rules can be very complex, there is no way to create classes for all possibilities.

    - domain validation
    This is validation that can not be performed with merely the submitted form values, it needs other resources. Examples include checking if a submitted user ID for a news item is valid. I believe you should not include this kind of logic into the form validation classes.

  25. #25
    SitePoint Wizard Chris82's Avatar
    Join Date
    Mar 2002
    Location
    Osnabrück
    Posts
    1,003
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I agree, that it should be possible to create classes which cover most cases of syntactic validation. If the user needs more he can subclass from one of the Filters / Validators and create his own checks.

    Semantic validation as you point out, is really difficult. The example I used, only assumed that input between two fields is equal. I think, I will try to solve this kind of dependency and hopefully write classes that can be extended and adapted to the users' requirements.

    For the last type of validation, I agree that this should be handled elsewhere.

    Example: a search form which searches by a number
    All you can do is add a filter / validator to the field so that it only accepts numerical input. If you enter a number that does not exist somewhere, from the validation point of view, the input is still valid since it is a number.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •