Page 3 of 6

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

Posted: Thu Apr 24, 2008 8:15 am
by jmut
matthijs wrote:@jmut: sorry to say this and really no offense meant here, but: I read your post three times and I don't understand what you're saying. English might not be your primary language and neither is it mine so that could explain why I don't understand your post. But could you explain in some other easier way what you tried to say? I'd appreciate that, I am interested in what you have to say here.
edited post...please scroll up

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

Posted: Thu Apr 24, 2008 8:20 am
by jmut
webaddict wrote:Interesting topic. I agree that writing forms is one of the most tedious jobs out there. Nevertheless, I also have to agree with Mathijs in saying that automating this process could be really hard, considering the fact that designers and users will not (always) be pleased with a form that is generated per request. So it has to customizable.

The two options I've seen in this topic are:
  • Generating the form on the fly from a certain object (less code for developer, hard to customize from template).
  • Hand-writing the form (more code for developer, easy to customize from template).
From where I'm standing there are two different kinds of logic involved in handling a form. The first would obviously be showing the (x)Html form (so presentation), the second would be the logic for filtering and validation. Mathijs is right in saying the presentation part of the form should be easy to customize, but then, we're programmers thus lazy thus we don't like to type the same thing over and over. But, thinking it over, one could conclude that the presentation (xhtml) of a form is rather static, while filtering, validation and showing the errors or prefilling the form's values is dynamic because the user's input is not static.

From my point of view, the best form library would be the one that can generate a template, but only does it one time and not for every request. It would create a template that contains placeholders for both error messages as for prefilled values. But then, you're still left doing all the filtering/validation/prefilling logic, so you actually just want .... scaffolding?
Ok, simplest you can do is just pile up the actual input, selects and whatever using ZForm and just echo element by element...with no other html around whatsover. This will still do the prefilling, will do the filtering,validation and all, and desginer can do anything around those... I mean it's really the whole html up to him, instead of <input something... /> (this part will be autogenerated). He can move them around etc etc.

I mean I cannot imagine that it's is really a must that designer should add more attributes to tag or something. 99% of cases as long as he knows the class name , he is all set. + most probalby he won't even bother with element in particular but will surround with div with id...and use css to directly address particular element within div. As for javascript , I think onclick,onchcange has no place in element either (plus I don't know designer doing this ...only devs do), these should be window.onload defined or something like this.

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

Posted: Thu Apr 24, 2008 8:36 am
by inghamn
webaddict hit the nail on the head. For my money, code generators are where it's at, especially for forms; and a good scaffolding is the way to go. There's very few scaffoldings out there in PHP land, and none that I've seen generate code to work with ZendFramework, but it's fairly easy to write your own.

Having the forms as *mostly* XHTML view scripts saves me, the developer a metric ton of time when dealing with all of the customizations from the usabilty staff. There's little helpful notes to include, special fieldset groupings to do, and the actual layout of the fields is the most important part of a professional-looking system. I cannot envision any code to be able to do this, it takes a human designer.

But you can generate all the basic form XHTML, complete with basic output escaping and required fields. Just got done building a new system over here, and probably around 95% of the form XHTML has been customized per the usability designer. Input sizes changed, layout changed, some forms were even split up into several forms, accessed through a tab-based system.

In our stuff, all the basic code is now generated from looking at the database. Models, Controllers, and Views (forms). These files are then ready for all the customization. But they at least start with everything done in your choice of sane way. In our case, all the views escape output, all the models have setters which validate input. You most certainly end up customizing everything, but having the basics covered is where all the time savings for the developer come from.

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

Posted: Thu Apr 24, 2008 9:09 am
by webaddict
jmut wrote:I mean I cannot imagine that it's is really a must that designer should add more attributes to tag or something. 99% of cases as long as he knows the class name , he is all set. + most probalby he won't even bother with element in particular but will surround with div with id...and use css to directly address particular element within div. As for javascript , I think onclick,onchcange has no place in element either (plus I don't know designer doing this ...only devs do), these should be window.onload defined or something like this.
I can. Being the only designer, coder and usability expert in my company, I know that I have to edit the "simple" forms quite occasionally. A label that says "name" just isn't descriptive enough for some users. You can create a script that'll generate the form on the fly and provide hooks (such as id and classes), but that just won't cut it. By scaffolding the form, you have two advantages: 1) it produces simple xhtml code that your designer can actually change without bothering you for details on how to do it; 2) it's more effective, since the form doesn't have to be generated over and over and over. Fair enough, the second argument really just is a bubble of air, because that really won't make much of a difference, but still.
inghamn wrote:In our stuff, all the basic code is now generated from looking at the database. Models, Controllers, and Views (forms). These files are then ready for all the customization. But they at least start with everything done in your choice of sane way. In our case, all the views escape output, all the models have setters which validate input. You most certainly end up customizing everything, but having the basics covered is where all the time savings for the developer come from.
I concur.

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

Posted: Thu Apr 24, 2008 9:56 am
by jmut
webaddict wrote:
jmut wrote:I mean I cannot imagine that it's is really a must that designer should add more attributes to tag or something. 99% of cases as long as he knows the class name , he is all set. + most probalby he won't even bother with element in particular but will surround with div with id...and use css to directly address particular element within div. As for javascript , I think onclick,onchcange has no place in element either (plus I don't know designer doing this ...only devs do), these should be window.onload defined or something like this.
I can. Being the only designer, coder and usability expert in my company, I know that I have to edit the "simple" forms quite occasionally. A label that says "name" just isn't descriptive enough for some users. You can create a script that'll generate the form on the fly and provide hooks (such as id and classes), but that just won't cut it. By scaffolding the form, you have two advantages: 1) it produces simple xhtml code that your designer can actually change without bothering you for details on how to do it; 2) it's more effective, since the form doesn't have to be generated over and over and over. Fair enough, the second argument really just is a bubble of air, because that really won't make much of a difference, but still.
inghamn wrote:In our stuff, all the basic code is now generated from looking at the database. Models, Controllers, and Views (forms). These files are then ready for all the customization. But they at least start with everything done in your choice of sane way. In our case, all the views escape output, all the models have setters which validate input. You most certainly end up customizing everything, but having the basics covered is where all the time savings for the developer come from.
I concur.
Ok, if you want that much adding attributes to tag....can always do this..... with some method or something.... I mean this is minor trouble... generating scripts that you just edit.... I just don't see what hapeens when stuff needs to be rearanged and all, when you have to add new elements...do you regenerated whole script (are all changes of designer gone?)

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

Posted: Thu Apr 24, 2008 10:27 am
by inghamn
jmut wrote: Ok, if you want that much adding attributes to tag....can always do this..... with some method or something.... I mean this is minor trouble... generating scripts that you just edit.... I just don't see what hapeens when stuff needs to be rearanged and all, when you have to add new elements...do you regenerated whole script (are all changes of designer gone?)
In the case of database changes....your generators should not overwrite the existing views. Rather, you have your generators create/overwrite files somewhere else. Then you can copy and past then new input html from the generated code into your existing view script. Although, honestly, once you're up and running, you probably don't need to run the generator just to update the view script with one new database field. As a developer, you can just add the new field's XHTML to the appropriate view script by hand. We're talking about a single <input /> tag somewhere...no mess no fuss. If you DRY, you've only got one single view script that is THE form used on the system whenever something about that model is edited, right?


If you're doing major database refactoring, well, you've got bigger fish to fry. But you can still generate the new code and merge the generated stuff in by hand.

99% of the time, database changes involve adding a field or two here and there over time. That's easy to accomodate with generated code. Database refactoring is a pain no matter how you look at it.

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

Posted: Thu Apr 24, 2008 10:37 am
by matthijs
Ingham, you make it sound very easy. I'm sure many here would like to see how you do it. Can you show some code?

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

Posted: Thu Apr 24, 2008 11:10 am
by inghamn
I'm sure everyone's got different XHTML they would expect out of a generator, depending on their choice of framework and application style. Ours is geared towards our framework, but should make sense. For what it's worth, you can check out our work at http://opensource.bloomington.in.gov

Open the database
Show tables
foreach table you describe the table
foreach field you store the fields in an array.

Then, you can generate whatever XHTML you want for each table by looking at the field and it's type

Code: Select all

 
<?php
$PDO = Database::getConnection();
 
$tables = array();
foreach($PDO->query("show tables") as $row) { list($tables[]) = $row; }
 
foreach($tables as $tableName)
{
    $fields = array();
    foreach($PDO->query("describe $tableName") as $row)
    {
        $type = ereg_replace("[^a-z]","",$row['Type']);
 
        if (ereg("int",$type)) { $type = "int"; }
        if (ereg("enum",$type) || ereg("varchar",$type)) { $type = "string"; }
 
 
        $fields[] = array('Field'=>$row['Field'],'Type'=>$type);
    }
 
    $result = $PDO->query("show index from $tableName where key_name='PRIMARY'")->fetchAll();
    if (count($result) != 1) { continue; }
    $key = $result[0];
 
 
    $className = Inflector::classify($tableName);
    $variableName = Inflector::singularize($tableName);
 
    $dir = APPLICATION_HOME."/scripts/stubs/blocks/$tableName";
    if (!is_dir($dir)) { mkdir($dir,0770,true); }
 
 
/**
 * Generate the Update Form
 */
$HTML = "<h1>Update $className</h1>
<form method=\"post\" action=\"<?php echo \$_SERVER['PHP_SELF']; ?>\">
<fieldset><legend>$className Info</legend>
    <input name=\"$key[Column_name]\" type=\"hidden\" value=\"<?php echo \$this->{$variableName}->{$getId}(); ?>\" />
    <table>
";
foreach($fields as $field)
{
    if ($field['Field'] != $key['Column_name'])
    {
        $fieldFunctionName = ucwords($field['Field']);
        switch ($field['Type'])
        {
            case 'date':
            $HTML.="
    <tr><td><label for=\"{$variableName}-$field[Field]-mon\">$field[Field]</label></td>
        <td><select name=\"{$variableName}[$field[Field]][mon]\" id=\"{$variableName}-$field[Field]-mon\"><option></option>
            <?php
                \$$field[Field] = \$this->{$variableName}->dateStringToArray(\$this->{$variableName}->get$fieldFunctionName());
                for(\$i=1; \$i<=12; \$i++)
                {
                    if (\$i!=\$$field[Field]['mon']) { echo \"<option>\$i</option>\"; }
                    else { echo \"<option selected=\\\"selected\\\">\$i</option>\"; }
                }
            ?>
            </select>
            <select name=\"{$variableName}[$field[Field]][mday]\"><option></option>
            <?php
                for(\$i=1; \$i<=31; \$i++)
                {
                    if (\$i!=\$$field[Field]['mday']) { echo \"<option>\$i</option>\"; }
                    else { echo \"<option selected=\\\"selected\\\">\$i</option>\"; }
                }
            ?>
            </select>
            <input name=\"{$variableName}[$field[Field]][year]\" id=\"{$variableName}-$field[Field]-year\" size=\"4\" maxlength=\"4\" value=\"<?php echo \$$field[Field]['year']; ?>\" />
        </td>
    </tr>";
            break;
 
            case 'datetime':
            case 'timestamp':
            $HTML.="
    <tr><td><label for=\"{$variableName}-$field[Field]-mon\">$field[Field]</label></td>
        <td><select name=\"{$variableName}[$field[Field]][mon]\" id=\"{$variableName}-$field[Field]-mon\"><option></option>
            <?php
                \$$field[Field] = \$this->{$variableName}->dateStringToArray(\$this->{$variableName}->get$fieldFunctionName());
                for(\$i=1; \$i<=12; \$i++)
                {
                    if (\$i!=\$$field[Field]['mon']) { echo \"<option>\$i</option>\"; }
                    else { echo \"<option selected=\\\"selected\\\">\$i</option>\"; }
                }
            ?>
            </select>
            <select name=\"{$variableName}[$field[Field]][mday]\"><option></option>
            <?php
                for(\$i=1; \$i<=31; \$i++)
                {
                    if (\$i!=\$$field[Field]['mday']) { echo \"<option>\$i</option>\"; }
                    else { echo \"<option selected=\\\"selected\\\">\$i</option>\"; }
                }
            ?>
            </select>
            <input name=\"{$variableName}[$field[Field]][year]\" id=\"{$variableName}-$field[Field]-year\" size=\"4\" maxlength=\"4\" value=\"<?php echo \$$field[Field]['year']; ?>\" />
            <select name=\"{$variableName}[$field[Field]][hours]\" id=\"{$variableName}-$field[Field]-hours\">
            <?php
                for(\$i=0; \$i<=23; \$i++)
                {
                    if (\$i!=\$$field[Field]['hours']) { echo \"<option>\$i</option>\"; }
                    else { echo \"<option selected=\\\"selected\\\">\$i</option>\"; }
                }
            ?>
            </select>
            <select name=\"{$variableName}[$field[Field]][minutes]\" id=\"{$variableName}-$field[Field]-minutes\">
            <?php
                for(\$i=0; \$i<=59; \$i+=15)
                {
                    if (\$i!=\$$field[Field]['minutes']) { echo \"<option>\$i</option>\"; }
                    else { echo \"<option selected=\\\"selected\\\">\$i</option>\"; }
                }
            ?>
            </select>
        </td>
    </tr>";
            break;
 
            case 'text':
        $HTML.= "
    <tr><td><label for=\"{$variableName}-$field[Field]\">$field[Field]</label></td>
        <td><textarea name=\"{$variableName}[$field[Field]]\" id=\"{$variableName}-$field[Field]\" rows=\"3\" cols=\"60\"><?php echo \$this->{$variableName}->get$fieldFunctionName(); ?></textarea></td></tr>
        ";
            break;
 
            default:
        $HTML.= "
    <tr><td><label for=\"{$variableName}-$field[Field]\">$field[Field]</label></td>
        <td><input name=\"{$variableName}[$field[Field]]\" id=\"{$variableName}-$field[Field]\" value=\"<?php echo \$this->{$variableName}->get$fieldFunctionName(); ?>\" /></td></tr>
        ";
        }
    }
}
    $HTML.= "
    </table>
 
    <button type=\"submit\" class=\"submit\">Submit</button>
    <button type=\"button\" class=\"cancel\" onclick=\"document.location.href='<?php echo BASE_URL; ?>/{$variableName}s';\">Cancel</button>
</fieldset>
</form>";
$contents = "<?php\n";
$contents.= COPYRIGHT;
$contents.="
?>
$HTML";
file_put_contents("$dir/update{$className}Form.inc",$contents);
 
}
 

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

Posted: Thu Apr 24, 2008 11:25 am
by matthijs
Thanks for showing.

The big issue I see in your approach is that it only works if your forms map directly to your db tables. How often is that? I mean, you might want
- to not use all fields
- have forms for data input spanning many tables
- have forms not even related to a db table
- may want to add custom stuff to forms
etc etc

And last but not least - you still have to add validation/filtering to each form

So even though it might be a quick thing to put together the HTML for a few forms, that's only a small part of the whole work. And in my opinion, coding a few forms in HTML is not a lot of work at all. It's the whole package of HTML, validation, filtering, logic, etc.

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

Posted: Thu Apr 24, 2008 11:48 am
by inghamn
matthijs wrote:Thanks for showing.

The big issue I see in your approach is that it only works if your forms map directly to your db tables. How often is that? I mean, you might want
- to not use all fields
- have forms for data input spanning many tables
- have forms not even related to a db table
- may want to add custom stuff to forms
etc etc
The scaffolding generator is really just to get you started. It is never inteded to be the final version you ship. As such, one form per DB table is as good a place as any to start. Especially since, for production release, nearly ALL of your form views are going to customized ad nauseum by your usability designer to satisfy the blue-haired old ladies who are going to be actually using your system. (Okay, I'm in government, your userbase might be different)
matthijs wrote: And last but not least - you still have to add validation/filtering to each form

So even though it might be a quick thing to put together the HTML for a few forms, that's only a small part of the whole work. And in my opinion, coding a few forms in HTML is not a lot of work at all. It's the whole package of HTML, validation, filtering, logic, etc.
If you go to that URL and download the whole package, you'll see the approach our framework has taken, including generators for all the other stuff like models and controllers. It's true, form handling involves display an interface for the user, taking the stuff from the user and giving it to the model. In my view (FWW) validation/filtering/logic is best handled in the model. The controller calls setters in the model for each of the fields that are POSTed. If there's a problem, the model will complain, and the controller can do whatever it needs to for redirection or rendering a different view or whatever. The view just needs to make sure to escape the output. I know it's more of a J2EE thing to use actual setters written into the model, but since it's generated...meh, I don't have to type it all. And I can customize the validation as needed.

The main point, though, is that the XHTML for the form is going to be so heavily customized that trying to accommodate that in PHP code is a wild goose chase. Use whatever MVC style you like, and whatever framework you like. But writing generators to create yourself a basic working application, complete with sane starting validation et al, is well worth the time. I mean, do you really want to keep typing all those really long ZendFramework classnames by hand for all the controllers you're going to write? :wink:

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

Posted: Thu Apr 24, 2008 12:25 pm
by Christopher
I think this discussion pretty clearly show the major design issue with forms systems. Different developers have a different types of forms they typically implement. You could probably graph them with simple to complex on one axis, and from consistent to custom on the other. You can solve all of these forms problems from different directions. Each implementation style works, but some are better when you apply one style of form. jmut is happy generating the form in code, so something like Zend works. inghamn has done some really nice things with scaffolding and is happy taking generated code that is 80%/90% there and tweaking it to get the final from. I go a different direction and push the XHTML work completely onto the designer and only do the code necessary to make the form come alive.

From my graph above I can state for general types of forms:
1. simple fields/rules/filters and consistent layout
2. simple fields/rules/filters and custom layout
3. many types of fields/rules/filters and consistent layout
4. many types of fields/rules/filters and custom layout

It seems like the solutions come into three general types:
1. The entire form and surrounding XHTML is generated with PHP (like with QuickForm or Zend_Form)
2. The form layout is XHTML, but the form fields are generated with PHP. (inghamn's example does this)
3. The form layout and form fields are all in XHTML and the PHP only sets values or selections (Kieran style)

Do these descriptions cover all the ways that people here do forms? Obviously the HTML generation code will be different between these styles, but does the form handling code also differ?

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

Posted: Thu Apr 24, 2008 1:03 pm
by matthijs
That's a very nice summery. One I agree with.

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

Posted: Thu Apr 24, 2008 1:55 pm
by Christopher
matthijs wrote:That's a very nice summery. One I agree with.
The question for you, Jcart and me is whether we can create a set of solutions that use a common set of classes. A set of solutions that allow you to mix-and-match styles or migrate from one style to another easily.

I am getting the sense that there are these three XHTML styles above and maybe two styles of form handlers -- conventional if($form->isValid()) logic block style and the callback controller style.

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

Posted: Thu Apr 24, 2008 5:23 pm
by aliasxneo
arborint wrote:
matthijs wrote:That's a very nice summery. One I agree with.
The question for you, Jcart and me is whether we can create a set of solutions that use a common set of classes. A set of solutions that allow you to mix-and-match styles or migrate from one style to another easily.

I am getting the sense that there are these three XHTML styles above and maybe two styles of form handlers -- conventional if($form->isValid()) logic block style and the callback controller style.
Would it be possible to include XML anywhere in here?

For instance, where the entire form and XHTML is generated the actual XML can be generated first and then passed to a class that then parses and renders the form. This then can be modified so that for customization the XML can first be generated by the programmer (either by storing it in a file or at runtime) and then given to be rendered. Even more so for simple customizations the generated XML can be tweaked before being sent off to be rendered. This also includes the final option of being able to detail the entire form template in XML (thus making it completely customizable).

Just a thought that came across my mind while shifting through this topic.

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

Posted: Thu Apr 24, 2008 7:43 pm
by Christopher
aliasxneo wrote:Would it be possible to include XML anywhere in here?
Yes, although I would want it to be from configuration data in general. That could be XML, INI, YAML, or just an array. It should be format independent data that gets turned into an array internally.

So yes, you should be able to define the form using configuration data -- that is definitely a goal.

And interesting extension of this idea that we have discussed is that if you can create a tool like what inghamn has written -- but that produced XML/INI/YAML instead of HTML/PHP code -- then you could create a read write scaffolding system. So you could write out a basic scaffolding config file from the tool, the either edit the config file manually read the file back into the scaffolding tool to make changes.