SitePoint Sponsor

User Tag List

Results 1 to 20 of 20
  1. #1
    SitePoint Guru aamonkey's Avatar
    Join Date
    Sep 2004
    Location
    kansas
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Form class - Am I just being lazy?

    After the last monster form I wrote, I've decided I need an alternative to the way I handle forms. I'm getting tired of writing the html, the javascript validation, the php validation, and the error handling...etc.
    So I decided to start writing my own form class. I realize there are many others out there, but I wanted to build this from the ground up so that everything could be custom-tailored to my needs (and so I would know what every line of code was doing).

    I'm about half done writing the thing and it seems to be working well. I'm just looking for opinions on my process:

    a form is started like this:
    PHP Code:
      $form = new form('myForm''form_test.php');
      echo 
    $form->start(); 
    then adding say, a text field goes something like this:
    PHP Code:
      echo $form->text('my_text_field1'45'default value''d-force''Custom error msg here'); 
    where d-force is a shorthand for the regex validation type (i'm also working on a validation class simultaneously)

    Now by this one line of code, the html for the form input is created, and all it's attributes are stored in a session array. javascript validation and error handling is automatically written in a variable, which once the form is done I call by:

    PHP Code:
      echo $form->finish();
      echo 
    $form->writeJavascript(); 
    Then on the form handling page: A loop is done through the session information about the form. it looks for the corresponding $_POST information and revalidates/cleanses the input. If there are errors it bounces the form back to the original page with the errors shown. all this is done by:
    PHP Code:
      $f = new formRegister();
      
    $f->registerPostVars(); 
    Now this is all seems to be working great. It saves me a ton of time for every form.

    My questions are:
    1) do you see any potential security holes in this method?
    2) Is duplicating all the form attributes in the session just adding a lot of overhead to the site? The site (I hope) will someday have a fair amount of traffic...
    3) Am I just being lazy? Would I be better off in the long run just hardcoding everything?

    Thanks,
    aamonkey

  2. #2
    SitePoint Wizard triexa's Avatar
    Join Date
    Dec 2002
    Location
    Canada
    Posts
    2,476
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am not quite sure why are you storing everything in a session?

    I would either put something like req_ in front of the field name to make it required, or a hidden field which listed required fields...

    If the user has disabled cookies (which AFAIK also disables sessions) then you're stuck
    AskItOnline.com - Need answers? Ask it online.
    Create powerful online surveys with ease in minutes!
    Sign up for your FREE account today!
    Follow us on Twitter

  3. #3
    SitePoint Guru aamonkey's Avatar
    Join Date
    Sep 2004
    Location
    kansas
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    well, the thought behind storing everything in a session is that I only want to define the name of the variable and the validation type 1 time, and have it remembered on the processing page. Like I said, I'm being lazy and I don't like to retype things

    Sessions should be ok on cookie-disabled computers with the session id appended to the url, shouldn't they?

  4. #4
    SitePoint Wizard triexa's Avatar
    Join Date
    Dec 2002
    Location
    Canada
    Posts
    2,476
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm I suppose so.

    I dunno, I don't really have a strong argument at the moment (give me time! hah) but I wouldn't go the session route
    AskItOnline.com - Need answers? Ask it online.
    Create powerful online surveys with ease in minutes!
    Sign up for your FREE account today!
    Follow us on Twitter

  5. #5
    SitePoint Guru aamonkey's Avatar
    Join Date
    Sep 2004
    Location
    kansas
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    it does feel a little 'hacky', and I am concerned about the size of the session files getting too large with large forms and (hopefully) 1000's of users online...but I haven't come up with a better idea. If you think of a strong argument for junking the session idea, i'm all ears :-)

  6. #6
    SitePoint Addict
    Join Date
    Mar 2005
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have used a better way for form processing. The key for including validation inside the form itself, is to parse it twice. Firstly for javascript validation, after submit you need to parse the form into php to read the validation requirements.

    It's not simple but using, xml_parse_into_struct() you can read the html file and also read validation parameters set in the form.

    Personally I use frm_required, frm_letters, frm_email and many other settings as class names to define how the form should be processed. No need for session (except for returning errors) and you have the benefit of only setting one set of data requirements that both javascript and php can interpret.

  7. #7
    SitePoint Guru aamonkey's Avatar
    Join Date
    Sep 2004
    Location
    kansas
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    you've piqued my interest, but I'm concerned about a couple things--mainly this:
    Quote Originally Posted by rossriley
    It's not simple but using, xml_parse_into_struct() you can read the html file and also read validation parameters set in the form.
    How are the validation parameters set in the html form, exactly? If it's done with hidden inputs, it won't suit my needs since that can be easily spoofed.

  8. #8
    SitePoint Addict
    Join Date
    Mar 2005
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You're right, that's the thing that always made me avoid this method.
    The key is to parse the form twice.
    Javascript reads the class values from the form sent to the user, this is the one that could be spoofed. After submission though, php reads the form straight off the server, completely ignoring the info the user has set. I then compare the values that php is expecting to what the user has sent.

    The user can send what they like, but unless they can interfere with the physical file on the server, which they obviously can't, then your data can be validated twice without having to code the validation twice....

  9. #9
    SitePoint Addict
    Join Date
    Mar 2005
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    And sorry I forgot to say, it is done by specifying a class. eg....
    Code:
    <textarea name="address" id="address" class="FMrequired FMtext FMmaxlength-200"></textarea>

  10. #10
    SitePoint Evangelist ClickHeRe's Avatar
    Join Date
    Mar 2005
    Location
    Ottawa, Canada
    Posts
    580
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have 2 things working together in my framework/experiments but are separate and can be replaced.

    FormHandler which loads a form from a source which can be XHTML or XML. Then I can manipulate the form's input type dynamically if needed. The handler loads the source so it controls nothing related to presentation. For example, this form :

    form2.xml
    Code:
    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <form action="/fw/index.php" id="test" method="post">
      <div>
        <label>blah</label>
        <input type="text" id="blah" name="blah" value="bloh'arf" />
      </div>
      <div>
        <label>bleh</label>
        <select id="bleh" name="bleh">
          <option value=""></option>
          <option value="theme">theme</option>
          <option value="script">script</option>
          <option value="addon">addon</option>
        </select>
      </div>
      <div>
        <label>blih</label>
        <textarea rows="5" cols="15" id="blih" name="blih">Ha Ha Ha</textarea>
      </div>
      <div>
        <input type="submit" id="_SUBMIT_" name="_SUBMIT_" value="Submit" />
      </div>
    </form>
    The FormHandler accepts as constructor 5 parameters :

    $f = new FormHandler( 'forms/form2.xml', $_POST, array( 'blah', 'blih' ), FALSE, 'invalid' );

    - the file to load the form from
    - the input data submitted an recaptured (used to repopulate the fields of the form in case of an error when the 4th param is FALSE)
    - an array of the field IDs that are in error
    - a boolean indicating that we want to reset the contents of the form (if FALSE the form will populate the fields with the 2nd parameter array passed as the submitted data)
    - the CSS class value to assign to error fields (can be NULL for none)

    You can control the parameters with functions such as
    $f->setAction( 'blah/arf.php' );
    $f->setInput( 'blah', "text\ntext2" );
    $f->setAttribute( 'blah', 'attrib', 'value' );
    ...

    then you have 2 functions to the output

    $f->toXHTML( ); which throws the form as a whole string
    $f->getDOM( ); which you can access the DOM object that has the form data to aggregate it further (I use XML/XSL templating in my framework)

    Secondly, I have a class for InputValidation which can be used for form validation but for any other validation you think about.

    The rules are written into a file like this:

    rules.xml
    Code:
    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <rules>
      <field rule="NotNullRule" id="_SUBMIT_" data="Submit" />
      <field rule="RegexRule" id="blah" data="/^blah$/">
        <message>blah must be "blah" !!!</message>
      </field>
      <field rule="NotEmptyRule" id="bleh">
        <message>bleh missing!</message>
      </field>
      <condition rule="MatchDataRule" id="bleh" data="theme">
        <field rule="NotEmptyRule" id="bluh">
          <message>bluh missing! if bleh == theme</message>
        </field>
      </condition>
      <field rule="NotEmptyRule" id="bloh" >
        <message>invalid bloh! must not be empty</message>
      </field>
    </rules>
    This is loaded by the InputValidator :

    $v = new InputValidator( 'validation/rules.xml', $_POST ) ;

    It traverses the rule file where the rules are objects that obey an interface with a single function called validate( );

    Some conditions can be optionally checked as seen in the XML with the condition block where the child rule is only checked if the condition rule is matched which enables some more complicated validation process where conditionals apply.

    As seen in the XML file, there are some error messages (optional) for some field rules, you can then use

    $v->getMessages( ); to retreive an array of the error messages from the fields that are invalid.
    $v->getFields( ); which returns an array of the invalid fields

    Finally, you use $v->isValid( ) to assess the validity of the input. The input can come from form or another source.

    Hope this gives you ideas which is the point of this whole post.

    The classes are not yet completed as I'm currently refactoring some parts of them after I had new ideas. If you would like them, I could post them here later.
    David

  11. #11
    SitePoint Wizard
    Join Date
    Jan 2004
    Location
    3rd rock from the sun
    Posts
    1,005
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    99% of my forms are for backend control, via a login - so I make sure they are using JS enabled browsers - or they lose their session.

    If they submit anything funny - I know who they are, I keep telling them I know their names.

    Given that, I made some classes that do all JS validation, on the backend I just shakedown/sanitise all incoming input, thats all the get[], post[] and server[] vars and basic check for overloads.

    I have been using a forms "god class" for a couple of years, I know now why it is a "poorly written class", and I daresay given the time I would rewrite it and improve it.

    After making the form class (instantiation looks just like yours) The best timesaver I taught myself is to reuse the same form for input and editing.
    kinda:
    if var isset put it in the form:
    PHP Code:
    //[text(name,value,countdowner)]
    // only fills in a value if one is set
    $newform->text('fieldone','"$s->p['fieldone']"',1); 
    The forms generally show some extra "edit only" links like "Delete" depending on the previous action - if isset(fieldone) show Delete button

    This is still written using mainly procedural code, but doesnt half reduce the amount of writing I do.

    I call the js in the final call to the form:
    PHP Code:
    //Wont allow the form to be submitted unless fieldone has some data in it.
    $newform->JSNotNullSubmit("fieldone","You must fill in field one");
    //OR
    //Wont allow the form to be submitted unless more complicated validation code in  fieldone.js returns true.
    $newform->JSScriptSubmit("fieldone.js"); 
    I am now finding I am doing away with straight textfields too in favour of embedded wysiwyg editors.

    As I learn more patterns, I guess I will learn much better ways of doing it.
    I hope this information helps.
    3) Am I just being lazy? Would I be better off in the long run just hardcoding everything?
    No and no.
    isempty()

  12. #12
    SitePoint Guru aamonkey's Avatar
    Join Date
    Sep 2004
    Location
    kansas
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thanks for the ideas guys--some interesting things I hadn't thought about so far...

  13. #13
    SitePoint Enthusiast
    Join Date
    May 2002
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just a suggestion. Why don't you just use HTML_QuickForm, everything that you need is in there. Combined with HTML_QuickForm_Controller, you have everything you want in a form .

  14. #14
    SitePoint Addict
    Join Date
    Mar 2005
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Don't like HTML_QuickForm personally because it produces bad HTML with inline styles, unless it's changed drastically since last time I looked.....

  15. #15
    SitePoint Enthusiast
    Join Date
    Nov 2005
    Location
    The Netherlands
    Posts
    84
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Personally, I would create forms using classes as such;
    PHP Code:
    class Form
    {
        private 
    $elements;

        public function 
    __construct( ... )
        {
            
    //
            // create form start etc
            //
        
    }

        public function 
    addControlleriFormHandler $H )
        {
            
    $this->elements[] = $H;
        }
        
        public function 
    Render()
        {
           
    $output '<form name="' $this->config'name' ] . '" ...>';

           foreach( 
    $this->elements as $e )
           {
              
    $output .= $e->Render() . "\r\n";
           }

           
    $output .= '</form>';

           return 
    $output;
    }

    class 
    TextField // implements iFormStandards
    {
        
    //
        // Vars and get/set methods
        //

        
    public function Render()
        {
          return 
    '<input type="text" name="' $this->config'name' ] . '" ... />';
        }
    }

    $form = new Form();
    $text1 = new TextField;
     
    $form->addController$text1 );
    echo 
    $form->Render(); 
    I think the example tells how to implement the script

  16. #16
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    Australia
    Posts
    101
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    There is also a different way to add forms to a page, one which i think hasn't been mentioned as yet.

    Creating forms using a declarative template syntax component style, e.g. ASP.NET, WACT, Prado
    Lots info from WACT's wiki, http://www.phpwact.org/pattern/templ...component_apis
    http://www.phpwact.org/wact/template_syntax


    I think you may call Prado as Forms on steroids, e.g.
    See http://xisc.com/demo/ the Rental Wizard example, and

    the following tests, which basically runs through most of the components
    http://xlab6.com/prado/tests/web_tests.php

    Each individual component, e.g. textbox, is quite close to x4t's post above.
    http://cvs.sourceforge.net/viewcvs.p...hp?view=markup
    However, Prado is a framework, thus not so easy to just pull a few classes here and there to make things work.

  17. #17
    SitePoint Addict
    Join Date
    Mar 2005
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This might be an interesting point to get everyone's thoughts.
    I've always favoured keeping forms in the 'view' layer of an application, for a couple of reasons.
    Firstly forms are an integral part of a page layout and something that page designers will always create in visuals and prototypes.
    Secondly, the data that is collected and the format it is collected is also part of the presentation layer. So the application needs a date but how you collect that depends on the user interface, which is a part of the presentation layer.

    So because of this I came up with the method I outlined above, of allowing both the presentation layer and the controller to read the form and embedding the data requirements in the form.

    I know many frameworks, rails included, provide form helpers to automatically generate forms from the controller layer, but is this correct? or should forms be a part of the presentation layer?

  18. #18
    SitePoint Addict
    Join Date
    May 2003
    Location
    The Netherlands
    Posts
    391
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by rossriley
    This might be an interesting point to get everyone's thoughts.
    I've always favoured keeping forms in the 'view' layer of an application, for a couple of reasons.
    I also consider forms to be a part of the view.

    Quote Originally Posted by rossriley
    Firstly forms are an integral part of a page layout and something that page designers will always create in visuals and prototypes.
    I agree also in that they're just another way of visually representing data from a model. IMHO, in a web environment you should consider the functionality of a form as embeded within the browser and does not belong to the web application itself. But I'd go a little further in the way designers may affect that visual representation. I distiguish between markup and style very much the way it actually works. To me, the markup of the form is a fixed issue and it would belong in a "core" template. These "core" templates are not for the designers to play with because they're based on the standard markup as given by W3C, and would only depend on the content type the application is using for the output. So you'd have for instance HTML4 templates, XHTML1 templates, etc.
    The designers would be able though to adjust the style for the forms.
    Quote Originally Posted by rossriley
    Secondly, the data that is collected and the format it is collected is also part of the presentation layer. So the application needs a date but how you collect that depends on the user interface, which is a part of the presentation layer.
    I don't agree, however, with you on this one. The format of the data, at least in my case, is given and determined by the application itself, as it is where the knowledge of the needed format is coming from. The controller would then indicate to the view which format it will be expecting and the view would use a representation that copes with that need. As the form gets submitted, the controller would always receive the right format. In general, I try to keep the view as dumb as possible and use it only as a way of representing data. Of course, things get slightly more complicated when you use some kind of (JavaScript/VbScript/Flash) widget that would enhance the functionality of the view, but if you keep considering it as a standalone unit and the only thing you do from the controller is choosing the adecuated widget for the right action, it becomes not more than a less-dumb view, from the application point of view.
    The only exception to this rule I have found up till now is working with a widget which makes use of XmlHttpRequest. I still have to figure out that one. I have some clues, but it's not totally resolved for me at the moment.
    There’s more than one way to skin a cat.

  19. #19
    Non-Member Gator99's Avatar
    Join Date
    Sep 2004
    Location
    Florida
    Posts
    613
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Generally I use the same concept of creating the form, js and sql through a class, but the class is not included in the web application to render the form every time a page is requested. I use it as a utility to generate static code for the front end and to generate the required sql/validation for the application form handlers. Basically its a script that connects to the database, and upon choosing a table and pressing a button it spits out all the html, js which I pass on to the designer, and the sql/php validation is generated to insert/update the data in the form handler. And uusally some or all of the code is slightly modified in certain cases so you don't have to worry about exceptions as you would when trying to do a catch all class on the backend.

  20. #20
    SitePoint Enthusiast
    Join Date
    Apr 2004
    Location
    US
    Posts
    51
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ClickHeRe
    The classes are not yet completed as I'm currently refactoring some parts of them after I had new ideas. If you would like them, I could post them here later.
    It look awesome, please post it here. Thanks alot


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
  •