Page 5 of 6

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Sun Apr 27, 2008 1:52 pm
by Mordred
My examples contained both form generation and submition handling, so it should be enough for a comparison. I too work with the assumption that the code will be dealing with the database (which is the most common case, so that's what my code generation aims at), but it is easily overriden anyway.

@inghamn
the model handles all input filtering and validation. The view escapes all the output.

Yep, +1 on that.
The controller that uses a form is expected to handle what comes back when the form is POSTed.
Also agreed, Zend's way and my way seem to be the same as well. It's quite sensible if you think about it.

What I'm missing from your code is a mechanism for reacting to violations of field-specific rules. Sure you enforce some by means of the setter methods, but you would not notice minimal length restrictions for example, unless there's custom code in the save() method.
What jumps out at me right away, is that my form handling stuff definitely assumes a model.
That's perfectly reasonable in my book. An object is after all (among other things) a collection of values perceived as a logical whole - exactly like what a submitted form is.
I definitely don't use an object for forms, it always seems like too much work.
You're not using templates, which would be a candidate for a "form object", so for your implementation it does indeed make little sense.

In my way of doing things object-templates do a good job - they handle very easily the case of supplying default values for a form (something which is not present in the Zend code btw. arborint?)

There are three security problems I can see with your code though:
1. As the very minimum, is_callable() in the controller.
2. No type checking in the model setters.
3. XSS with $_SERVER['PHP_SELF'].
4. (optional ;) ) I don't know what your "blocks" are, but you must be aware that with that .inc extension they will be served "as is" by default, so if there's a remote chance of them containing something useful for an attacker, do protect them with .htaccess

@arborint: How come we're not seeing skeleton examples as well? I haven't checked how it would be used about forms yet.

-----

Btw, something that is not visible in my code, but all my widgets with the specific exception of the login one (not the one in the sample above, I have a hand-written one) happilly work with $_REQUEST - it works well for almost all cases and allows more flexible implementations without much ado (links that partially init a form for example).

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Sun Apr 27, 2008 2:29 pm
by Christopher
Mordred wrote:My examples contained both form generation and submition handling, so it should be enough for a comparison. I too work with the assumption that the code will be dealing with the database (which is the most common case, so that's what my code generation aims at), but it is easily overriden anyway.
It is difficult to see the differences without being able to run them. Inghamn's needs Template and Block classes not provided. Your code assumes even more. Yours looks like it needs even more supporting classes. I posted a Zend_Form example because I thought everyone could actually run it.
Mordred wrote:
the model handles all input filtering and validation. The view escapes all the output.

Yep, +1 on that.
I agree, but only that putting filtering and validation in the Model is one option. The argument for putting filtering and validation in the Controller is that it simplifies implementing forms. Although in that case the Model is simply implicit in the Controller -- I would hope the proper dependencies would maintained.
Mordred wrote:What I'm missing from your code is a mechanism for reacting to violations of field-specific rules. Sure you enforce some by means of the setter methods, but you would not notice minimal length restrictions for example, unless there's custom code in the save() method.
Yes, there is filtering but no validation -- so no specific error messages.
Mordred wrote:You're not using templates, which would be a candidate for a "form object", so for your implementation it does indeed make little sense.
It looks like he is using templates to me. What do you mean?
Mordred wrote:In my way of doing things object-templates do a good job - they handle very easily the case of supplying default values for a form (something which is not present in the Zend code btw. arborint?)
No, I have not supplied default values -- yet. I was trying for simple first.
Mordred wrote:@arborint: How come we're not seeing skeleton examples as well? I haven't checked how it would be used about forms yet.
We have not finalized implementions yet and are looking for input. Hence my interest here and in Zend. Ninja and I have had a long running discussion about forms and the lack of what we consider an good implementation.

I will try to put some examples together and post a download. There are several ways to do forms in Skeleton, so I need to put together clear examples of each. The goal is to support:
- generated HTML or templates,
- with a Model or without,
- loosely coupled if($form->isValid()) style or integrated callback style.
- possible to work with scaffolding -- either generated code or data
- create simple forms easily
- flatten the amount of work to create complex forms
- support for Javascript to do client side validation and setting values/selections
- etc.

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 8:04 am
by VladSun
arborint wrote:VladSun, obviously I want to know what General_Time_Report and General_Time_Report_Model look like. ;) Are they based on a General_Report and General_Model? How general purpose is your system. Even if it just did sub-totals and grand-totals for you it would be nice.
It wasn't the code implementation, but the ideology I am presenting. In my case, a write-once PHP code generates the MVC classes by getting the DB table/db SP/db view description. It has some common with Mordred's way, but at the same time it's somehow opposite to it.

In my *implementation* there must be several stored procedures defined (it can also use Views or plain SQL query but that's not the point):

- sp_(report_name); // get the data
- sp_(report_name)_totals; // get the totals data
- sp_(report_name)_total_count; // get the total row count of sp_(report_name) generated data in case sp_(report_name)_totals is not defined (needed for pagination).

The implementation requires name-to-name mapping in DB and code domain (that's for filtering, custom validation, etc. and applies to SP and its fields names).
So, if the DB designer changes the sp_(report_name) parameters, no code changes are needed, because the code domain follows the DB domain.

I must say, that I'm not very happy with my particular implementations (because of the deadlines there are many "hacks" in it), but I'm very happy with the main idea and the result I got by using it. I'll present the implementation when all the bugs and hacks are beeing fixed.

I was inspired by http://codeigniter.com/user_guide/gener ... lding.html :)

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 9:28 am
by jmut
I am getting very confused here :)
So many examples, what are we after really.
Examples shown seem really dependent on other stuff, building models, code generation and kind of all other unrelated stuff I think.
Will peraphrase the arborint's ZForm example with addressing his issues on it.
arborint wrote: 1. I needed to pass it a Zend_View to make it work. It seems like it is wired into their View system.
2. The dl/dt/dd tags may seem a little strange. Most people would use div or label I think.
3. We might want to set the class property for form fields and tags containing them. And the dl has a class, but no id.
1. Of course there is some degree of using the already built in components in ZF (Zend_View in this case) but I don't see view as drawback or something, you build a string out of it...it's up to you where you echo it...that doesn't change form handling I think. Seems kind of weird
to have form handled 50/50 by ZForm and some other solution for example.
2. In code below 'no_decorator' element has disabledDefaultDecorators..hence no dl.dt etc... only decorator for rendering the actual element is used.
Clearly decorator design pattern is used here..which allows building any output you want...or none..if you want to use just the meta data of a form element.
Main reason behind setting such default dl dd dt tags for all input elements, is:
* you get pretty good overview of the form by default..with no css
* you get strict html complient code
* in general should be able to decorate those with css anyway you want
* you can very easily disable default decorators if not like it
3. I put
* class for each element
* id for the dl tag in front (first calls in My_Form::init())
* id for dd tag of one specific element

I would do the form something like that as would be possible to use same form in different places. Last element used...has no decorators, hence no html rendered around it

Code: Select all

 
//index.php
<?php
$my_include = '/path/to/zendframework/library/';
set_include_path($my_include . PATH_SEPARATOR . get_include_path());
 
include_once 'Zend/View.php';
require_once 'MyForm.php';
$form = new  My_Form();
$form->setAction('')
     ->setMethod('post');
$form->addElement('submit','commit' ,array('label' => 'Send'));
 
if (!empty($_POST)) {
    if ($form->isValid($_POST)) {
        echo '<pre>' . print_r($form->getValues(), 1) . '</pre>';
    }
}
echo $form->render(new Zend_View());
 

Code: Select all

 
//MyForm.php in same dir as index.php 
<?php
 
include_once 'Zend/Form.php';
 
class My_Form extends Zend_Form
{
    public function init()
    {
        $this->addDecorator('FormElements')
             ->addDecorator('HtmlTag', array('tag' => 'dl', 'id' => 'dl_id' , 'class' => 'zend_form'))
             ->addDecorator('Form');
        $this->addElement('text', 'fname', array(
            'validators' => array(
                array('NotEmpty', true, array(
                        'messages' => array('isEmpty' => 'First name required.')
                )),
                array('Alnum',false,true),
                array('StringLength', false, array(3)),
            ),
            'required'   => true,
            'class' => 'fname_class',
            'label' => 'First name',
            'description' => 'Please fill in first name', 
        ));
        $this->addElement('text', 'lname', array(
            'validators' => array(
                array('NotEmpty', true, array(
                        'messages' => array('isEmpty' => 'Last name required.')
                )),
                array('Alnum',false,true),
                array('StringLength', false, array(3)),
            ),
            'required'   => true,
            'class' => 'lname_class',
            'label' => 'Last name',
            'description' => 'Please fill in last name',            
        ));
        $this->addElement('text', 'email', array(
            'validators' => array(
                array('NotEmpty', true, array(
                        'messages' => array('isEmpty' => 'Email required.')
                )),
                array('EmailAddress'),
            ),
            'required'   => true,
            'class' => 'email_class',
            'label' => 'Email address',
            'description' => 'Give your email address for spamming purposes, please', 
        ));
 
        //->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form'))
 
        $dlDecorator = $this->email->getDecorator('HtmlTag');
        $dlDecorator->setOption('id','id_of_dd');
 
 
        $this->addElement('text', 'no_decorator', array(
            'validators' => array(
                array('NotEmpty', true, array(
                        'messages' => array('isEmpty' => 'Email required.')
                )),
                array('EmailAddress'),
            ),
            'required'   => true,
            'class' => 'no_decorator_class',
            'disableLoadDefaultDecorators' => true,
            'decorators' => array(
                            array('ViewHelper')
                            )
        ));
    }
}
 
 

Code: Select all

 
<form enctype="application/x-www-form-urlencoded" action="" method="post"><dl id="dl_id" class="zend_form">
<dt><label for="fname" class="fname_class required">First name</label></dt>
<dd>
<input type="text" name="fname" id="fname" value="" class="fname_class"></dd>
<dt><label for="lname" class="lname_class required">Last name</label></dt>
<dd>
<input type="text" name="lname" id="lname" value="" class="lname_class"></dd>
<dt><label for="email" class="email_class required">Email address</label></dt>
<dd id="id_of_dd">
<input type="text" name="email" id="email" value="" class="email_class"></dd>
 
<input type="text" name="no_decorator" id="no_decorator" value="" class="no_decorator_class">
<dt>&nbsp;</dt><dd>
<input type="submit" name="commit" id="commit" value="Send"></dd></dl></form>
 

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 9:51 am
by VladSun
jmut wrote:Examples shown seem really dependent on other stuff, building models, code generation and kind of all other unrelated stuff I think.
You build up your code after your DB design, right?

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 10:19 am
by inghamn
jmut wrote:I am getting very confused here :)
So many examples, what are we after really.
Heh, yeah - we seem to be floundering unable to describe what we really want. Without knowing what our goal is, we can't really compare solutions. I went back and re-read Ninja's original post
The Ninja Space Goat wrote: Not only is form development the longest, most tedious portion of development, it's also one of the most important to get right. Forms are the interface to your user. Because of this, they must be both secure, as well as easy to use....

Why is it so hard to find a good solution for this in PHP? I think it has a lot to do with the fact that PHP is just too damn verbose. From the definition of the form to the template that renders it, PHP just requires too much work.
It sounds like we're looking for something that's :
1. Secure
2. Easy
3. Minimal Verbosity

Maybe not in that order, I don't know.

All these solutions are going to end up requiring some library or framework code, since no one wants to do Security checks every single time they process user input. Comparing and evalutating the security aspect of solutions may be a bigger task than we can cover here. That would mean doing code reviews on everyone's full library code. Not everyone likes the Zend_Form stuff, and alot of us end up with our own libraries.

But if we can be confident in the security of our library code (black box that it is), then we can look at the actual bulk of frustration with forms...the ease of use for developers. It sounds to me like we're trying to find a way to invisibly handle all the security stuff (filtering, validation, escaping, etc...) and try to save ourselves the most possible time while developing applications. Oh, and we want it to be simple (not complex or verbose).

I doubt anyone's frustrated because the solutions are too insecure...we get frustrated because it's too much work. Speaking for myself, I spend the bluk of my development time editing controllers. For my money, that's where I've tried the most to simplify things. The libraries handle things (in a black box sort of way) so that I can write controllers with the least amount of code I could think of.

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 11:17 am
by jmut
VladSun wrote:
jmut wrote:Examples shown seem really dependent on other stuff, building models, code generation and kind of all other unrelated stuff I think.
You build up your code after your DB design, right?
Mmm..no

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 11:34 am
by John Cartwright
jmut wrote:
VladSun wrote:
jmut wrote:Examples shown seem really dependent on other stuff, building models, code generation and kind of all other unrelated stuff I think.
You build up your code after your DB design, right?
Mmm..no
I think because the database design influences our code and our decisions, the database structure should come first.

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 11:46 am
by jmut
Jcart wrote:....
I think because the database design influences our code and our decisions, the database structure should come first.
I think this issue is for a whole other topic.
The original post in my mind was more concerned about handling form data(so you get something valid and ready for use)...and no concern of persisting it (database or whatever means).

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 1:59 pm
by VladSun
MVC should achieve separation between the Model, View and Controller. So, if changes in the logic of the Controller should not involve (in general) changes in the Model, and changes in the View should not involve changes in the code of the Controller and Model, why not extend this separation so that changes in the Model (not logical, but structural) should not involve changes in the code of Controller/View (in particular - forms)?

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 2:49 pm
by Christopher
jmut wrote:I am getting very confused here :)
So many examples, what are we after really.
Well it is a long story, but in general it is Ninja's search for the best forms library, and my trying to implement one for Skeleton. This has been going on for a while: ;)

viewtopic.php?f=19&t=75444
viewtopic.php?f=19&t=65715
viewtopic.php?f=19&t=65715
jmut wrote:Examples shown seem really dependent on other stuff, building models, code generation and kind of all other unrelated stuff I think.
Yes and no, because while many forms need a formal model object, many others (like an contact form that only emails) are much simpler or have a Transaction Script to write the form data to a datasource.
Will peraphrase the arborint's ZForm example with addressing his issues on it. And on top of that, if the Model is supposed to be independent of the View/Controller then it really should not effect the design of the form handler.
jmut wrote:1. Of course there is some degree of using the already built in components in ZF (Zend_View in this case) but I don't see view as drawback or something, you build a string out of it...it's up to you where you echo it...that doesn't change form handling I think. Seems kind of weird to have form handled 50/50 by ZForm and some other solution for example.
I was not talking about mixing frameworks, but it seems like it should be able to render HTML without needing a Zend_View object. There is no external purpose for the dependency -- it just is.
jmut wrote:2. In code below 'no_decorator' element has disabledDefaultDecorators..hence no dl.dt etc... only decorator for rendering the actual element is used.
Clearly decorator design pattern is used here..which allows building any output you want...or none..if you want to use just the meta data of a form element.
Main reason behind setting such default dl dd dt tags for all input elements, is:
* you get pretty good overview of the form by default..with no css
* you get strict html complient code
* in general should be able to decorate those with css anyway you want
* you can very easily disable default decorators if not like it
3. I put
* class for each element
* id for the dl tag in front (first calls in My_Form::init())
* id for dd tag of one specific element
I have to say that your code example does not make me like the Zend_Form solution more. It seems convoluted. And there are strange things like that you are telling it to decorate a <dl>, but you would know that it output a <dl> until you actually got it to work. And using the pattern name "decorator" seems to be a little odd. I have never heard that term used by people building HTML/CSS. The code that you posted seems like it is working around and undoing things. For example, you need to call addDecorator() and then specify 'no_decorator' to get it to work. Or the settings are arcane like "'decorators'=>array(array('ViewHelper'))" ? I do think the array() syntax is clearer than the OO interface -- I like that.

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 2:59 pm
by Christopher
VladSun wrote:MVC should achieve separation between the Model, View and Controller. So, if changes in the logic of the Controller should not involve (in general) changes in the Model, and changes in the View should not involve changes in the code of the Controller and Model, why not extend this separation so that changes in the Model (not logical, but structural) should not involve changes in the code of Controller/View (in particular - forms)?
Yes, though there is some disagreement about the View-Controller dependencies you state. And I think many forms solutions, like Zend_Form and QuickForm, combine View and Controller, which are the two of the three that you can combine ...

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Mon Apr 28, 2008 4:52 pm
by Kieran Huggins
Forms are a special case in MVC, since they essentially collect data that is tied directly to the model. If you add a model attribute (like "favourite_colour") then you'll need to update the view to collect (and/or show) the new attribute. I really don't think that smells at all.. there's only so much automation you can really build in before your UI suffers.

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Tue Jul 01, 2008 5:50 am
by acsandeep
hi,

I think you people may want to take a look at this code snippet. I am using php2go framework which makes handling FORMS a breeze. To create a form with a template you need 3 components. First a PHP file, second a XML file which defines the form and lastly a template file. The XML file contains all the rules,datasources which define the form fields. It is even possible to add fields dynamically. It does the client side and server-side validations automatically. Please see the attached screenshots for HTML output and validations.

Download URI of the framework. You can try to run the examples in the example folder. I am just a user of the framework not the dev. The main site seems to be down for the last 2-3 days.

Code: Select all

 
//$doc is a document object instance to output xhtml content of the page
$form = new FormTemplate('form.xml', 'form.tpl', 'myForm', $doc);
if ($form->isPosted()) {
        if($form->isValid()){
     $values = $form->getSubmittedValues();
     //do something with the values.
       }else{
       return $form->getContent();
}
}else{
       return $form->getContent();
}
 
###################################################
Here is the XML file

Code: Select all

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE form SYSTEM "..\..\docs\dtd\php2go_forms.dtd">
<form>
    <section name="a1" id="a1" required_flag="T">
        <hiddenfield name="case" value="change_password" />
        <passwdfield style="reg1" name="current_password" label="Current Password"  accesskey="P" minlength="6" maxlength="255" required="T" />
        <passwdfield style="reg1" name="new_password" label="New password"  accesskey="P" minlength="6" maxlength="255" required="T" />
        <passwdfield style="reg1" name="repeat_password" required="T" maxlength="255"  label="New password (repeat) "  accesskey="P">
            <rule type="EQ" field="new_password" message="Password do not match"/>
        </passwdfield>
        
        <buttons>
            <button name="submit" type="SUBMIT" img="style/images/btn_submit_pink.gif" />
        </buttons>
    </section>
</form>
###################################
Here is the template file

Code: Select all

<div id="form_client_errors" {errorStyle}{errorDisplay}>{error}</div>
 
    <div class="clr"><!-- --></div>
<div class="padTop27"><!-- --></div>
<div class="boxLft1">
<!-- error box -->
<!--<div class="errorBox">Please enter Username<br />Please enter Password</div>-->
<div class="formLftTxt1">{label_current_password}</div>
<div class="formRgt1">{$current_password}</div>
<div class="clr"><!-- --></div>
<div class="padTop20"><!-- --></div>
 
<div class="formLftTxt1">{label_new_password}</div>
<div class="formRgt1">
  {$new_password}
</div>
<div class="clr"><!-- --></div>
<div class="padTop20"><!-- --></div>
 
<div class="formLftTxt1">{label_repeat_password}</div>
<div class="formRgt1">
  {$repeat_password}
</div>
 
<div class="clr"><!-- -->
<div class="padTop40"><!-- --></div>
<div style="padding-left:252px;">{$submit}</div>
</div>

Re: I figured out why I'll never be happy w/ php forms libraries

Posted: Tue Jul 01, 2008 11:48 am
by Christopher
acsandeep wrote:I think you people may want to take a look at this code snippet. I am using php2go framework which makes handling FORMS a breeze. To create a form with a template you need 3 components. First a PHP file, second a XML file which defines the form and lastly a template file. The XML file contains all the rules,datasources which define the form fields. It is even possible to add fields dynamically. It does the client side and server-side validations automatically. Please see the attached screenshots for HTML output and validations.
That looks like about the same style as most forms solutions. And it seems to have the same kinds of implementaion limitations. It is actually not that difficult to create a forms solution like this that requires a specific implementation.

I think the questions in this thread were about create a truly flexible system. What if you don't want to use XML? Or not use PHP templates? What if you want to put error messages next to each field? What if you want custom validation rules? Or input filtering? What if you want to use a Model that contains the validation?