Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="info"><ac:parameter ac:name="title">Proposal has been revised in-depth on 14 October 2006. Please take a look at revision 0.2 thoroughly if you have already read and commented revision 0.1</ac:parameter></ac:macro>

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend_Form Component Proposal

Proposed Component Name Zend_Form
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Zend_Form
Proposers Simon Mundy
Ralf Eggert
Revision 0.1 - 28 August 2006: Initial proposal.
0.2 - 14 October 2006: revised proposal. (wiki revision: 16)

Table of Contents

1. Overview

Zend_Form is a component for creating, validating and processing form data.

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

  • One or multiple instances per page
  • Provides an interface for creating forms for a variety of end-uses (XHTML for current proposal, other end-uses to be implemented)
  • Allows auto or manual data population (can utilise Zend_Filter_Input)
  • Allows fine-grain control of form optional parts for display, validation, filtering and generation

4. Dependencies on Other Framework Components

  • Zend_Exception
  • Zend_Input_Filter
  • Zend_Filter (tbc)
  • Zend_Validator (tbc)

5. Theory of Operation

Zend_Form provides a set of loosely coupled parts and view helpers to model, validate & filter, display, generate and process a form. The core of Zend_Form is the form model which is the only mandatory part. All other parts are optional, yet all parts work together smoothly with the form model.

Form model

With the form model the programmer will be able to model a specific form. It is an abstract class which needs to be extended to implement a specific form model. The model class provides the required functionalities to:

  • add the unique id for the form
  • add form fields
  • set defaults for each form field
  • accept values for the form fields (e.g. from raw $_POST data, a Zend_Filter_Input object or even a simple array)
  • pass all form attributes, values and fields to an array

It also provides an abstract setup method which needs to be implemented in an extended form model class to add fields to the specific form.

Every form field is an object with a name property, an unset Zend_Validator property, an unset Zend_Filter object and a simple isValid() method.

Validation and Filtering

Since the validation and filtering part is optional the programmer can use his own validation method. Anyway the validation and filtering part provides the required functionalities to:

  • add a Zend_Validator object with validation rules (e.g. Zend_Rule_Range) to a field of the form
  • add a Zend_Filter object with filter rules (e.g. Zend_Filter_Int) to a field of the form
  • add allowed keys for a selection using a Zend_Rule_IsIn validation rule
  • validate the form
  • get the error status of invalid form fields

Based on the added Zend_Validator objects a form renderer will get some relevant information about how to display a specific form field, e.g. to display the "maxlength" attribute for text input fields or to specify if a select takes only one or more options. Also the allowed select options will be set with validation rules (Zend_Rule_IsIn).

Extended form fields

There are a set of form field objects which extend the basic Zend_Form_Field. They do not add much more functionality to Zend_Form_Field except setting up the Zend_Validator object for the form field with a set of validation rules and setting up the Zend_Filter object with a set of filter rules.

For example the Zend_Form_Field_Text sets up the Zend_Validator object with the Zend_Rule_String validation rule. Optional it takes a range for the text field and adds a Zend_Rule_Range validation rule to the Zend_Validator. Selections which expect only one option to be selected, can be handled by Zend_Form_Field_Enum. Selections which expect none, one or more options to be selected can be handled by Zend_Form_Field_Set.

Zend_Form_Field can easily be extended by the programmer to add custom validation and filter rules.

View helpers

The view helpers are optional as well and extend the currently available view helpers by taking a form object to generate the output (e.g. XHTML) for

  • text fields
  • password fields
  • textareas
  • checkboxes
  • radio buttons
  • select lists
  • file upload fields

All view helpers take a reference to an field of the form object to identify values and other attributes set by the form object. The view helpers also examine the attached Zend_Validator object for the output (e.g. to set the "maxlength" for text inputs). Furthermore the view helpers take a list of other attributes for displaying the form field (e.g. "class", "size", "rows", "title").

For a select list, checkboxes and radio buttons the view helper will add the keys and corresponding values to display. Enum selections can be display as single selects or radio buttons. Set selections can be displayed as multiple selects or checkboxes.

To display validation errors there is a view helper to get an array of all unmatched validation rules for a specific form field or the whole form. Based on this the appropiate errors messages can be displayed.

Note: it still needs to be discussed if the current view helpers (release 0.1.5) should be kept or overwritten.

Automatic rendering

Again the rendering module is optional, so the programmer can handle the rendering of the form in every way he wants to, for example with the view helpers mentioned above. The rendering module will provide the required functionalities to

  • take further display attributes for each form field
  • organize form fields into sections (fieldsets)
  • generate the output code (e.g. XHTML) for a single field
  • generate the output code (e.g. XHTML) for the complete form

Note: the layout of these generated forms will mostly be limited to a linear layout but can be changed with CSS.

Automatic form generation

This optional module generates a form model with all fields from a record of a table (Zend_Db_Table_Row) or from a XML data record. Also some validation rules will automatically be added when appropriate, e.g. set maxixum chars, allowed keys for selections, etc.).

The generated form class can be cached or saved and extended with additional validation and filter rules.

Form processor

This optional module accepts validated form data and processes it according to business needs (Note: Darby, please specify in more detail, what a form processor should do and how it should do it).

Form controller

This optional part extends the Zend_Controller_Action to add a set of methods to handle form building, form validation, form rendering and form processing and can be extended to build specific controllers.

6. Milestones / Tasks

  • Milestone 1: Form building and form rendering with Zend_View helpers (UC 01, UC 02)
  • Milestone 2: Render form completely and render form to an array (UC 03, UC 04)
  • Milestone 3: Form validation and filtering with Zend_Validator and Zend_Filter (UC 05, UC 06, UC 07); NOTE: can not be completed until Zend_Validator and Zend_Filter can be used!
  • Milestone 4: Automatic form generation (based on a database table or an xml file) and form processing (UC 08, UC 09)
  • Milestone 5: Improve the client side of the form handling with Javascript validation, AJAX interaction and more.
  • Milestone 6: Handle Xforms

7. Class Index

Form model

  • Zend_Form
  • Zend_Form_Exception (extends Zend_Exception)
  • Zend_Form_Field
    • Zend_Form_Field_Text
    • Zend_Form_Field_Enum
    • Zend_Form_Field_Set
    • Zend_Form_Field_File

View helpers

  • Zend_View_Helper_FormElement (acts as a factory to a Zend_Form_Render object)

Automatic rendering

  • Zend_Form_Renderer_Abstract
    • Zend_Form_Renderer_Xhtml
      • Zend_Form_Renderer_Xhtml_Input
      • Zend_Form_Renderer_Xhtml_Text
      • Zend_Form_Renderer_Xhtml_Select
      • Zend_Form_Renderer_Xhtml_Textarea
      • Zend_Form_Renderer_Xhtml_Checkbox
      • Zend_Form_Renderer_Xhtml_Radio
      • Zend_Form_Renderer_Xhtml_Button
      • Zend_Form_Renderer_Xhtml_Hidden
      • Zend_Form_Renderer_Xhtml_File
    • Zend_Form_Renderer_Xform

Automatic form generation

  • Zend_Form_Generator_Abstract
    • Zend_Form_Generator_Db
    • Zend_Form_Generator_Xml

Form processor

  • Zend_Form_Processor

8. Use Cases

The use cases will build a simple form with the following form elements:

  • 'username': an input type=text for username (minlength = 5, maxlength = 32)
  • 'password': an input type=password for password (minlength = 5, maxlength = 16)
  • 'email': an input type=text for email
  • 'language': a single select for a language selector with an associative array ('en' => 'English', 'oz' => 'Strine', 'nz' => 'Kiwi');
  • 'accept': a checkbox for site acceptance

9. Class Skeletons

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Aug 28, 2006

    <p>At the first glance it looks like a QuickForm clone. Which is a very bad thing as it duplicates QF's flaws.</p>

    <p>For starters it's mixing business logic with presentation. I, as a web devoloper, want to place form elements, titles or even sections on my own. I don't want any code to be involved in visual appearance. </p>

    <p>As a programmer, I don't wan't to have any user frontend "strings" in the code - element names, section names, element comments, button captions all belong to the views. It's way to hard to make localized pages if you have your strings thrown throughout the code. And it would be great if validation error strings would also be placed directly in the views. I don't want to have any presentation markup in my bussiness variables! HTML is a presentation part, it doesn't belong to the controller or model parts of MVC.</p>

    <p>The way I see it is to have a Form object in the code which will gather values and set defaults on form values. Then you may have a validator object which a programmer may choose to use. But I would rather have this FormValidator object pass a Form at constructor level. And then view helpers which will just use the Form object and/or the Validator to prepare it's elements - form xhtml, auto set constraints from validation data (ie. maxlength). </p>

    <p>I will probably comment more when I find some time to analyze the code better. For now I have just skimmed it through.</p>

    1. Aug 28, 2006

      <p>I take your point, although I don't see it being too difficult to pass on the render responsibilities to the View anyway. </p>

      <p>In the instance, though, of a dynamically generated form (for example a CMS database record) how would you propose separating the two layers without requiring too much 'double handling' from the Controller and the View? I.e. You'd need to populate your form twice (once with the field types, default values and validators, once with labels, decorators) and potentially pass along the source of the form structure to both Controller and View which IMO is a bit klunky.</p>

    2. Aug 29, 2006

      <p>Hi Michael,</p>

      <p>thanks for your input so far. I hope you get some more time to analyze the proposal in depth.</p>

      <p>Regarding the QuickForm clone argument. Since QuickForm is the "eierlegende Wollmilchsau" (German for "all-in-one device suitable for every purpose") for building forms any other form component will look more or less like a QuickForm clone at some stage. </p>

      <p>In addition to Simons comment to pass the form object to the view for rendering you could also use the toArray() method and pass the results to your view for rendering.</p>

      <p>Best Regards,</p>

      <p>Ralf</p>

  2. Aug 29, 2006

    <p>Ok, guys. I have read it thoroughly now but I'll answer your remarks first.</p>

    <p>Simon, it's not a matter of difficulty. Why would I want anything to render the form on my behalf in the first place? As a webdesigner I would like to have a fine grained control over form element placement. Maybe I want to have address form elements placed on one line with only one label? And the rest not lined in a top-bottom manner. </p>

    <p>But let's work on some example - GMail search: </p>

    <p><ac:image><ri:attachment ri:filename="gmail-search.png" /></ac:image><br />
    ( <a class="external-link" href="http://images.aie.pl/php/gmail-search.png">http://images.aie.pl/php/gmail-search.png</a> ) </p>

    <p>How much work do you need to do to prepare a SIMPLE form like that? Everything you need in your business logic are the pure values and an information if these values are correct. You don't need to know anything about a form visual structure or even where the values come from. You just need to get them in order to make use of them. And the controller part shouldn't do anything besides that.</p>

    <p>Then you have a user frontend - that's what (X)HTML is for. I don't want to model the look of the form in php! It's awkward! I would like to place any single element or the label anywhere I wish. And moreover, you don't need any element labels or any text in the controller code. What do you need a comment like 'e.g. today, Friday, Mar 26, 3/26/04' for in the php code? Nothing. Or 'Date within'?</p>

    <p>What I would like here, is view helpers to create form elements only (form, input, textarea, password, etc). Similar to the ones that are already in the framework but with one exception - they should use values you defined in your business code, in Form objects. They should automatically set defaults, values, merged posted values, etc. So you don't have to pass them through the view attributes yourself.</p>

    <p>And then comes a time when I want to switch places of 'Search' and 'Date within' elements (see the above image). It's a simple thing - you just switch their positions in the html. The code is unaffected since it doesn't matter where the elements are. But with a form modeled in the code, you have to change element sections and it's a lot of unnecessary work if you have to analyze the code. Not to mention it's completely unintuitive.</p>

    <p>Now for the automatically generated form. You don't need such functionality in the main trunk of the form handling module. It's a useful thing if you want to hack a quick form for dictionary based tables. But let's face it - would you honestly create such a form for the customer? Me? No, never. But if you insist you can create another object (renderer for instance) which will take a real Form object as a parameter and quickly render your form for you. But don't make it an integrated feature, make it totally optional. I would like to avoid loading it's code with any html form.</p>

    <p>I haven't touched the validation stuff yet but I will. Christopher Thompson's validator proposal should be taken into consideration here.</p>

    <p>I don't know if any of you worked with xslt as a templating engine. It's a system where your view is really, and I mean really separated from the business code. And the form which will be similar to QF will just not make it there. Of course if you wish to keep the presentation data out of the php code.</p>

  3. Aug 29, 2006

    <p>First of all, I am happy to see that a form component has been proposed for the Zend Framework. On the other hand, I have to agree with Michael - this is a QuickForm clone, inheriting all the problems that QuickForm has.</p>

    <p>Don't get me wrong: I'm a long-time QuickForm user and one of the authors of DB_DataObject_FormBuilder, so I've used it quite a lot and in general, I like it. But you can only get so far until things become really complicated.</p>

    <p>1. I18N. As Michael said, you don't really want strings that are printed on screen to be defined in the backend. All output should be defined in the view component, including error messages when a rule condition is not met.</p>

    <p>2. In a Web 2.0/AJAX/insert-buzzword-here world, you'll want to add Javascript event handlers, custom script elements etc. to your form. Again, this should always be done in the view component.</p>

    <p>3. Form layout. It is nice to have a default renderer that can output your form with just one call to a render() method. It is tremendously useful for rapid prototyping. The ability to be able to define a form completely in the background, for example using a FormBuilder component that derives the form elements from a ORM layer, can only be weighed in gold. However, as soon as you leave the prototyping stage you'll want fine-grained control over the placement of each and every form element - this possibility must always be there!</p>

    <p>As another reference for a good form component, please have a look at patForms:
    <a class="external-link" href="http://trac.php-tools.net/patForms">http://trac.php-tools.net/patForms</a></p>

    <p>The advantage of patForms is that it allows both ways of constructing forms: You can either define a form automatically or by hand using only the API functions (just like QuickForm), <strong>or</strong> you can just write a plain HTML form, placing a few special XML attributes into the element tags for defining, for example, rules. This HTML snippet can then be parsed (and cached for later re-use) by the form component and you can use the resulting form object to evaluate validation etc. in the backend.</p>

    <p>It also features adaptors for various database layers so that form objects can both be constructed from database records and automatically write back their values to a database.</p>

  4. Aug 29, 2006

    <p>Another link to add as a reference... the QuickForm authors themselves are currently discussing the design for a successor to QuickForm here:</p>

    <p><a class="external-link" href="http://quickform.mamasam.com/wiki/">http://quickform.mamasam.com/wiki/</a></p>

    <p>Possibly a good source for additional ideas, although I haven't seen anything on the separation of controller and view yet.</p>

  5. Aug 29, 2006

    <p>We're off to a good start! I agree, this has undeniably sprung from QuickForm because both Ralf and myself have been longtime users and it's always easier to start from something you know. And it can be a bit daunting to have that completely ripped away and look at the problem from another angle, but I'm confident that a better solution will arrive from doing it this way.</p>

    <p>Martel, I haven't had any XLST experience but I do want to push to make this Zend_Form component play nicely in both the controller and the view. I also want to ensure we don't need to abstract the form-building process so heavily that we also need to rely on config files to construct them.</p>

    <p>I guess I need some clarification on a few conceptual issues before I can look at turning the code on its head.</p>

    <p>I can appreciate the need for more customisable forms - it's one of the reasons I am dissatisfied with QuickForm currently. And for forms that I know which fields are going to exist (and what type they are) I can imagine the proposed Zend_Form being very easy for me to convert to this layout. For example:-</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $form = Zend_Form::factory(new Zend_Form_Html(array('title' => 'myform')));
    $form->addElement($form->createElement('id1', array('type' => 'text'));
    $form->addElement($form->createElement('id2', array('type' => 'text'));

    will go into my layout as:-

    <?php echo $form->renderHeader(); ?>
    <div class="grp1">Enter firstname, lastname: <?php echo $form->id1->renderElement() . ' ' . $form->id1->renderElement() ?></div>
    <div id="goButtonElement"><?php echo $form->createElement('id1', array('type' => 'text'))>renderElement() ?></div><?php echo $form>renderFooter(); ?>
    ]]></ac:plain-text-body></ac:macro>

    <p>So I can still instantiate form elements within the view if I wish to. I could set up the form structure in the controller, add validators and perform post-processing and then add all the labels , properties and display-related info in the view if I wish to.</p>

    <p>But how do you propose I would - for example - create a dynamic form from a CMS. A table record, similar to Markus' comment above. I still need to construct the form in some fashion within the controller for validation and processing. Why not add elements/titles there? If the controller is responsible for setting the language/locale of the site (I18N as above) then why can't it tell the form which labels/error codes to use and the view can then translate those into the appropriate multi-lingual response? How does a view know how to logically assemble a dynamic form without somehow referring to a model which, in a lot of cases, is manipulated within the controller before it even gets to the view?</p>

    <p>I'm also not denying that there is a lot of View-based logic that needs to be kept well clear of the controller. A perfect example here is the Quickform client-side validators which produce some truly horrid javascript MULTIPLE times - I know I'd much rather use a more graceful library like Prototype or MochiKit to hook into these forms for some fancy effects and validation. See the code examples above where we can set an element's callback dynamically for both server and client-side validation - this could be achieved within the view.</p>

    <p>What I would like is some use-cases or existing solutions that we could use to see how to practically solve some of these issues. I acknowledge that the current proposal will need to come some way to achieve Form Nirvana but - speaking for myself only - this will be a lot harder for me to visualise without some further detailed discussion and more concrete code (even pseudo-code for now).</p>

  6. Aug 29, 2006

    <p>I don't have much time on me at the moment so I will just throw another hint to supplement Markus' remarks. For the problem of what should go where take a a look at the XForms specification and tutorials. </p>

    <p>To make the long story short, XForms <model> may be a good indicator of what should be placed in the business logic and the rest of the "xform", which is placed in the body, should hint what goes to the view part.</p>

    <p>Some examples:
    <a class="external-link" href="http://www.w3.org/TR/xforms/sliceG.html">http://www.w3.org/TR/xforms/sliceG.html</a></p>

    <p>I'll comment your post at a later time, Simon.</p>

  7. Aug 30, 2006

    <p>Simon, there's little sense in doing a clone of existing software. Judging from the code, I can do almost the same things with a QF as with the proposed code. If you are going to take this route, then why not help develop QF2? And why any user should choose a ZF Form module when he has a very similar code and a lot more mature to choose from?</p>

    <p>I'm also a long time user of QF and just like you and many others I have stumbled upon QF's lack of certain features. And that's why I have so negative viewpoint when it comes to duplicating it's structure and API. I would like to see some fresh approach, which may have it's own weaknesses of course, but it may shine in the areas where there is no other good alternative.</p>

    <p>I have been thinking about a good form framework design for a while but I never have had so much time on me to actually develop it. So I put my great hopes in your proposal. But since it's your code you will do what you want, and I may only give you some pointers if you choose to go a different way.</p>

    <p>Now, I see it as a bunch of modules, highly independent of each other. There should be one mandatory item which is the form model itself. The rest should be totally optional:</p>

    <ul>
    <li>(mandatory) Form model. It's a module where your form should be modeled. It's where you choose your field types and their defaults. This module will also get the values out of the request and initialize form objects accordingly. It does not contain any visual stuff or the validation. It's only responsibility is to prepare, hold and MAYBE modify the data.</li>
    </ul>

    <ul>
    <li><ac:link><ri:page ri:content-title="optional" /></ac:link> Validation. Module which takes a form and adds a validation to it's elements. May be designed as a form decorator or in any other way. But it also should be optional - programmer may choose to use his own validation with our form framework.</li>
    </ul>

    <ul>
    <li><ac:link><ri:page ri:content-title="optional" /></ac:link> View part / renderer. It's a part which takes a form model and renders a form out of it. It can render a whole form or only designated parts like it's single elements. It's a module which will need some additional strings to be defined IN IT to render the whole form for you. It can also use the validators to render appropriate errors.</li>
    </ul>

    <ul>
    <li><ac:link><ri:page ri:content-title="optional" /></ac:link> Generators. It's a module which tries to create a form model out of some alien data, like from a table record.</li>
    </ul>

    <p>And now we come to the flow of the form.</p>

    <p>First flow:</p>

    <p>0. User accesses a page.</p>

    <p>1. Form gets generated and is initialized with defaults. You don't need any validation in that part, because the user may be shown a form which will be processed in another controller (think search or login box visible on every page). </p>

    <p>2. Form view gets generated with a help of View module.</p>

    <p>Second flow (after user fills data and submits):</p>

    <p>1. Form gets generated again but the same model may be used as it very generic. Form gets initialized with request data and defaults if there's a need for it. </p>

    <p>2a. Form gets validated with appropriate validator module. If it is validated correctly view module is never used.</p>

    <p>2b. Form gets validated and is not passed. </p>

    <p>3b. Form view gets generated with a help of View module.</p>

    <p>As you can see validation and view may be not used at all! So there is no sense in loading it's code on every form access. The same goes with form generation module which will be used with a first step if necessary.</p>

    <p>The thing that needs some thinking is this - do we need to initialize all the select boxes and radio buttons before the validation? It's a thing I would like to avoid if the values are hard to get (ldap, soap, etc). You can of course cache them. Should a caching form be taken into the consideration?</p>

    <p>Of course this is still too generic but I hope it will at least make you think of something you two have not though of yet. </p>

    <p>And an "easier to gather" version of the XForms tutorials:
    <a class="external-link" href="http://www.w3.org/MarkUp/Forms/2003/xforms-for-html-authors.html">http://www.w3.org/MarkUp/Forms/2003/xforms-for-html-authors.html</a></p>

  8. Aug 31, 2006

    <p>Hi Michael, Simon and Markus,</p>

    <p>I read through your comments thoroughly, examined the links you provided and thought through your ideas in-depth now (wow! five "th" in one thentence) <ac:emoticon ac:name="wink" /> </p>

    <p>I tried to summarize all of this in a bit of code to see if I really understood what you want Zend_Form to work like. And I also tried to keep Xforms in my mind for this.</p>

    <p>First of all I examined for HTML forms which elements exists and what attributes they take. Then I divided them into attributes which should be set by the controller and attributes which should be set by the view. Based on this overview I figured out what Zend_Form element types we would need (please see attached file <a href="http://framework.zend.com/wiki/download/attachments/3596/form_elements.pdf">form_elements.pdf</a>).</p>

    <p>For example in the controller you define a text field. In the view then you can decide if it should be displayed as a single row text field <input type="text">, as a multi row text field <textarea> or a password text field <input type="password">. </p>

    <p>The same applies for the selection field. You define a selection in your controller and in the view you can decide to build a radio button or a single select for a selection, that only accepts one value, or to build a checkbox or a multiple select for a selection, that accepts zero, one or many values.</p>

    <p>Te same applies also for the buttons. In the controller you only define a submit button and in the view you can choose if it should be display as a normal button or an image button.</p>

    <p>To illustrate all this with a bit of code I attached the file <a href="http://framework.zend.com/wiki/download/attachments/3596/Zend_Form_Reloaded.zip">Zend_Form_Reloaded.zip</a> with a sample controller and some sample view scripts. The controller handles the building and validation of the form. The sample script show some ways to display a form. </p>

    <p>This new approach might look quite complicated at the first glance. But it is very flexible. If you want to set all attributes for your form elements in your controller you can do it. But you can overwrite the attributes in the view or add attributes which should rather be set in the view if you like, e.g. to set localization values or to add CSS to your form elements. You could even render the whole form into an array and pass that to Smarty or any other template engine you like, if you want to do it that way. Or you can organize your elements into fieldsets in your view script.</p>

    <p>It will also be very easy to use a Zend_Config object to build the form and add further design attributes. Or we can use a form builder based on a Zend_Db_Table object to render form completely out of the box. </p>

    <p>What do you all think about this approach? I am looking forward to discuss this.</p>

    <p>Best Regards,</p>

    <p>Ralf</p>

  9. Aug 31, 2006

    <p>Ralf -</p>

    <p>Great work! I love the flexability and the separation between view and business logic.</p>

    <p>One question, what's the purpose of the "showAction"?</p>

    <p>Two suggestions, we may want add two methods "setDefaults()" and "addElements()" to the FormController. See below for example. My reasoning is that "setDefaults" or "addElements" would be good methods to override for forms that extend this base form controller.</p>

    <p><?php<br />
    protected var $form;<br />
    protected function setDefaults()<br />
    {<br />
    $defaults = array(...);<br />
    $this->form->setDefault($defaults);<br />
    }<br />
    protected function addElements()<br />
    {<br />
    $this->form->addElement(...);<br />
    ...<br />
    }<br />
    public function buildAction()<br />
    {<br />
    $this->form = Zend_Form::factory(...);</p>

    <p> $this->addElements();</p>

    <p> $this->setDefaults();</p>

    <p> ...<br />
    }</p>

    1. Aug 31, 2006

      <p>Hi Dale,</p>

      <p>I am not quite sure, if I understood what you mean with your suggestion. But the FormController should not really be a part of the Zend_Form component. I just created it in my example code for illustration purposes. Though, it is possible to create your own FormController if you like.</p>

      <p>Regarding your question abaout "showAction". I also added that method only to demonstrate the possible flow of form building, form processing and presenting the results when validation was successful.</p>

      <p>Best Regards,</p>

      <p>Ralf</p>

      1. Aug 31, 2006

        <p>Ralf -</p>

        <p>Thanks for the clarification. After looking over it again, it all makes much more sense. Scratch my suggestions.</p>

        <p>Dale</p>

  10. Sep 01, 2006

    <p>Ralf, no, it's still too close to QF's model. You just have moved some business logic out of the controller to the views. I won't go into discussing if this is something which shouldn't be done in MVC, but please have in mind views should only display model data. I would avoid creating objects there - be it Smarty or Form View models. And the stuff happening in the layoutform1.php should be in fact handled by appriopriate view helpers (or helper like object passed to the view). It's a fine example otherwise, a bit closer to being right. But it's design is still coupled to tight for my tastes.</p>

    <p>Now, couple of ideas. I haven't thought them thoroughly, so I don't really know if it's possible to achieve them with a lightweight approach. But anyway.</p>

    <p>In the controller code you don't need any information concerning field types, right? Everything you need it to know from the code's standpoint is a variable name in order to get the value out of the REQUEST data. So, why bother setting a type there? In fact you only may need a type of a variable, since you get strings and arrays from forms. But not necessarily. Well, as I have mentioned before - form business model is only holder for named values. You probably don't need anything else there.</p>

    <p>To create a form in visual manner, you need to know what type of form you are going to create - html standard form, xform, etc. But this is form designers choice. Give them helpers to create html they like - $this->formTextarea(), $this->xformSecret(), etc. But it should be as painless as possible so by feeding it a name it should automatically get the value (default or already posted info) from the above form model. In XForm though you probably should have something like $this->xformModel() to populate the head with those values instead. These view helper should also use Form Validation data to set appropriate attributes - ie. maxlength.</p>

    <p>The Zend_Controller_Action_Form as a base object to extend your controllers from may be another good idea. This way you can control the flow of the form on behalf of the programmer - testing if the form is new, reposted, validating when necessary, etc.</p>

    <p>But I have to admit something. I have rather vague picture of the form framework in my head. It's hard for me to explain it properly and it's for sure even harder for you to see it. So if you're going to just modify current structure then I would advise to just ignore my insights. Don't try to satisfy everybody because you will end up with a bloated code no one will ever use.</p>

    1. Sep 01, 2006

      <p>Hi Martel</p>

      <p>I think 'too close to QFs model' may be getting in the way of solving some difficult issues. QF wouldn't have been adopted so widely if it wasn't successful at answering some baseline requirements. Yes - it's flawed and it's slow, but it's also pretty good at what it does.</p>

      <p>One area that still has me confused in your responses is how validation is handled in your ideal form. I agree about making the form lightweight in the controller - you don't want to pollute it with display info if it's not required. But assigning field types to the form is more than simply describing how it looks - it affects validation. E.g.</p>

      <ul>
      <li>A text field is different from a textarea in that line breaks are not possible.</li>
      <li>It's impossible to tell that a select should only return 1 value or an array of values if you haven't specified if it's a multiple select or not.</li>
      <li>If you haven't populated a select option list before validation, how do you know if the submitted data was actually a selectable option?</li>
      <li>How can you validate a file upload if you're not taking the $_FILE superglobal into the picture (which you wouldn't if you didn't allow for a file input when inspecting the form values)</li>
      <li>A disabled form element shouldn't have its value set in the submitted data</li>
      </ul>

      <p>And even above this, how can we trust that the data supplied to us matches the original source? Through misadventure or malicious intent, form data can be forged or injected and without some idea of what we're validating against then it's more than likely we provide ineffective validation and we open up a form component to abuse.</p>

      <p>It could be argued that we could add more validation filters to reduce this dependency on the field types, but I think ultimately heading down that direction would be enforcing a bad answer onto a flawed question. After all we still want to make this form both easy to use and safe to use out-of-the-box.</p>

      <p>All that said, I fully agree that we need to find the ideal blend of speed and code efficiency to reduce the amount of effort invested in simply creating/validating a form. I knew this one would be a tough one to crack as inevitably there will be a vast difference of implementation needs.</p>

      <p>Thanks for the updates Ralf - will respond to the new Form Controller idea as soon as possible</p>

      1. Sep 04, 2006

        <p>As I have said before, you validate the data that comes thru HTTP. As optional validators probably (see Christopher's proposal). You don't need to know where the data comes from - textarea or text. You only need to specify if the incoming data can contain spaces or not.</p>

        <p>When it comes to array or single value, again, it's not important. Validators will halt the execution when data is in a wrong format for your needs. As you said before - form is easily spoofed, so it really doesn't matter what kind of element you will present to legitimate user.</p>

        <p>To answer the question of prepopulating selects - the thing one is sure about is to get the data once - you will have it in an array, in key and value pairs. And the array will be used twice - in the appriopriate validator which will have to know what values are available and in the view while creating form element. You can bind them by hand or, as I have said in earlier posts, make the view module use validation data to prepopolate it's own structures. </p>

        <p>And now a file. You don't specify a type in incoming data. File does not come as a POST or GET data so you have to treat it specifically from the start. It's something that can't be treated as a normal data and QuickForm also treats it differently.</p>

        <p>Now a disabled element. Just as with XForms - if you don't need a value, then you don't create the structure in the base form object. But you can freely place as many view elements as you like. It just won't take their values into consideration.</p>

        <p>"And even above this, how can we trust that the data supplied to us matches the original source?"</p>

        <p>By the use of validation module. And you're never sure if it comes from your form or a modified one. Or even from a hand crafted request maybe. But it also doesn't matter - in php business logic you're interested in the data that is coming to you. And not it's source.</p>

        <p>What I am proposing is taking a XForms path, where you clearly separate the presentation from the data. It's totally different approach since QF and your solution relies on defining HTML Form structure in php and my solution centers around incoming data. And that's why I honestly want to discourage you from trying to incorporate those ideas to the current implementation. It's like rowing up the river.</p>

        1. Sep 04, 2006

          <p>I'll run with your thought process through a semi-typical form example. Sometimes it helps me to get more clarity if I can work with something tangible.</p>

          <p>I need a form to capture a username, password, an email address, a language selection and acceptance of site terms and conditions. Traditionally, I would use the following:-</p>

          <ul>
          <li>An input type=text for username (maxlength = 32)</li>
          <li>An input type=password for password (maxlength = 16)</li>
          <li>An input type=text for email</li>
          <li>A single select for a language selector with an associative array ('en' => 'English', 'oz' => 'Strine', 'nz' => 'Kiwi');</li>
          <li>A checkbox for site acceptance</li>
          </ul>

          <p>If we approach this they way you're suggesting (and I'll use pseudo-code or non-existent classes purely to illustrate some concepts) I thought it may pay to make the form more of a model itself.</p>

          <p>Then it may look something like this:-</p>

          <p>Controller</p>
          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[

          $form = new My_Form('myformid');
          $form->accept($_POST);

          if ($form->validate()) {

          $value = $form->getValues();
          var_dump($value);
          }

          $view->form = $form;
          $view->render('form.tpl');

          ]]></ac:plain-text-body></ac:macro>

          <p>Models</p>
          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          abstract class Zend_Form implements Countable, Iteratable
          {
          protected $_field;
          protected $_error = array();
          protected $_default = array();
          protected $_values = array();

          final public function accept($values)

          Unknown macro: { $this->_submit = $values; }

          final public function validate()
          {
          if (!count($this->_getSubmitValues()))

          Unknown macro: { return false; }

          $this->_setup();
          return $this->_validate();
          }

          public function getValues()

          Unknown macro: { return $this->_values; }

          abstract protected function _setup();

          protected function _validate()
          {
          foreach($this->_field as $field) {
          if (!$field->isValid())

          Unknown macro: { $this->setError($field->getId(), $field->getValidationError()); }

          }
          if ($this->hasError())

          return true;
          }
          }

          class My_Form extends Zend_Form
          {
          protected $_defaults = array('lang' => 'oz');

          protected function _setup()

          Unknown macro: { $this->addField('username')->addValidator(new Validator_Required()) ->addValidator(new Validator_IsType('string')) ->addValidator(new Validator_Range(5, 16)) ->addValidator(new Validator_Regex('/^w+$/')); $this->addField('password')->addValidator(new Validator_Required()) ->addValidator(new Validator_IsType('string')) ->addValidator(new Validator_Range(5, 16)) ->addValidator(new Validator_Regex('/^w+$/')); $this->addField('email') ->addValidator(new Validator_Email()) ->addValidator(new Validator_IsType('string')); $this->addField('lang') ->addValidator(new Validator_Required()) ->addValidator(new Validator_IsType('string')) ->addValidator(new Validator_IsIn($options)); $this->addField('accept') ->addValidator(new Validator_Exists()); $this->addFilter(new Filter_Trim()); // Works on all fields - default? $this->addFilter(new Filter_Striplines()); }

          }

          ]]></ac:plain-text-body></ac:macro>

          <p>Finally we have the view for the form. I won't get into JavaScript validation for now - that will come once this first hurdle has been passed.</p>

          <p>Here's the hand-crafted way (using the existing Zend_View_Helpers)</p>
          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[

          <h1>Enter user details</h1>
          <form id="<?php echo $form->getId() ?>" method="post" action="<?php echo $form->getActionPath() ?>">

          <fieldset>

          <p><label for="frm_username">Username</label>
          <?php echo $this->formText('username', $form->username->getValue(), array('size' => 32)) ?></p>
          <p><label for="frm_password">Password</label>
          <?php echo $this->formText('password', $form->password->getValue(), array('size' => 32)) ?></p>
          <p><label for="frm_email">Email</label>
          <?php echo $this->formText('email', $form->email->getValue(), array('size' => 32)) ?></p>
          <p><label for="frm_lang">Language</label>
          <?php echo $this->formSelect('lang', $form->lang->getValue(), null, $form->lang->getOptions()) ?></p>
          <p><label for="frm_accept">Accept the terms?</label>
          <?php echo $this->formCheckbox('username', $form->accept->getValue()) ?></p>

          <p><?php echo $this->formSubmit(null, 'Enter') ?></p>

          </fieldset>

          </form>

          ]]></ac:plain-text-body></ac:macro>

          <p>It feels more like a Zend_Db instance for me this way - which isn't a bad thing - and I do like the consistency of approach. I do still have doubts that we are still needing a lot of work to validate data when a lot of manual the validators/filters would be removed if we could use 'hinting' to achieve this within the form class itself (e.g. the select IsIn validator, or the IsType('string')). BTW, the IsType is useful to ensure some bunny hasn't tried to inject an array where you expect a string or vice-versa.</p>

          <p>Martel - am I closer to understanding you here?</p>

          1. Sep 05, 2006

            <p>As I have mentioned in a private mail, Simon, I don't have much time on me so I will make it very brief. Hope you will get the idea from the abstract code and it's scarce comments. The code itself was just created in 10 minutes, I don't have any working parts of this system. It's just a draft that will hopefully help understanding my previous rants.</p>

            <p>The only thing that is not covered is the passing of error strings to the views. The easiest way would be to provide a third parameter to addValidator but it will leave some view data in the business code. I have yet to think how one can put the strings directly in the views.</p>

            <p>There are also places where I'm not sure how things should be done properly - like how to pass $languages to form view elements.It needs some research.</p>

            <p>The objects are very loosely coupled. You don't need to use anything but first Form object. You can prepare your own html form by hand, you don't need to use validators, you don't need to use form controller, you aren't forced to use generators. And what's most important - you can easily use your own objects in place of the original ones.</p>

            <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
            $languages = array ('en' => 'English', 'oz' => 'Strine', 'nz' => 'Kiwi');

            // Form model

            $form = Form($_POST);

            $form->addDataSource('username');
            $form->addDataSource('password');
            $form->addDataSource('email');
            $form->addDataSource('language', $default = 'en');
            $form->addDataSource('accept', $default = 0);

            echo $form->getValue('email');
            $form->hasData(); // bool - true if submitted

            // Validators

            // - for a html form you will use:

            $validator = Form_Validator($form);
            $validator->addValidator('username', new Validator_Required());
            $validator->addValidator('username', new Validator_IsType('string'));
            $validator->addValidator('username', new Validator_Length(5, 16));
            $validator->addValidator('username', new Validator_Regex('/^\w+$/'));

            $validator->addValidator('language', new Validator_Enum(array_keys($languages)));

            $validator->validate();

            // - for a xform:

            $validator = XForm_Validator($form, $xmlschema = '/path/to/schema'); // string or even DOM object
            $validator->validate();

            $validator->hasError('username'); // bool

            // Generator
            // - just an idea from the top of the head. I generaly hate such generic generators

            $gen = Form_Generator_TableRow($form, Zend_Db_Table_Row $row, $prefill = true);
            $gen->setFormName('register');
            $gen->setFormID('fe_register');
            $gen->setElementID('username', 'fe_102');
            $gen->render(); // prints whole form, QF renderers like.

            // Form View

            $view->form = new Form_View($form, $validator);

            // we may set it here but I'm not sure if it's the best approach
            // maybe passing it to view would be better. I don't know

            $view->form->setData('language', $languages);

            // Zend FW Views

            $this->form->renderText('username', array('class' => 'fe_username'));
            $this->form->renderSelect('language'); // will use default from Form, display data from Form_View
            $this->form->hasError('username');
            $this->form->renderError('username');

            // Zend FW Controller
            // example idea of a form controller with strict method naming
            //
            // In createForm() you create Form object and return it
            // In show() you create appropriate View object (generator or plain) and pass it to the view
            // In execute() you, well, execute your businness logic - ie. saving new user to the database

            class Zend_Controller_Form extends Zend_Controller_Action {

            abstract protected function createForm();
            abstract protected function show($form, $validator = null);
            abstract protected function execute($form);

            protected function createValidator()

            Unknown macro: { return null; }

            public function indexAction() {

            $form = $this->createForm();
            $validator = $this->createValidator();

            if (!$form->hasData())

            Unknown macro: { $this->show($form); return true; }

            if (isset($validator) && !$validator->validate())

            Unknown macro: { $this->show($form, $validator); return true; }

            $this->execute($form);

            return true;

            }

            }
            ]]></ac:plain-text-body></ac:macro>

            1. Sep 05, 2006

              <p>I like the concept.</p>

              <p>"The only thing that is not covered is the passing of error strings to the views."</p>

              <ul class="alternate">
              <li>Could we have all the error strings in the view and use the method "$this->form->hasError('username');" to choose to display or not display the string?</li>
              </ul>

              <p>"There are also places where I'm not sure how things should be done properly - like how to pass $languages to form view elements.It needs some research."</p>

              <ul class="alternate">
              <li>Since the validator knows the "keys", could we create the "values" for the select in the view? Also, we should consider incorporating, or have a way to incorporate, the I18N work to display select values in other languages?</li>
              </ul>

              1. Sep 07, 2006

                <p>Yes, the idea is to keep error strings in the views, but the problem is that every field can have many error reports. So you have to get access to the info on which validator has failed the test somehow.</p>

                <p>And for the values in views - you have to know both there, the keys and the data, to create a select field.</p>

                <p>A for the I18N - that's one of the main reasons why we want to keep all the frontend strings in the views.</p>

                1. Sep 07, 2006

                  <p>What if the validator had its own view template? If the validator failed during the validation step in the controller, then it would pull its message from a view template and add it to a form message array sent back to the form view.</p>

                  <p>"And for the values in views - you have to know both there, the keys and the data, to create a select field."</p>
                  <ul class="alternate">
                  <li>The "values" of a select are only important to the view. The controller, validator, and form don't care what "value" you selected, they only care about the "key". So, why not use the view to set up the association between key and value? The view can get the keys from the validator and through some means, generate the association. Default could be value=key.</li>
                  </ul>

            2. Sep 06, 2006

              <p>Michael -</p>

              <p>What's the purpose of splitting the form and validator up? Why not attach validators to form elements?</p>

              1. Sep 07, 2006

                <p>Well, a couple of reasons. For starters you can use your own validation methods if you wish to. Next thing is the validation may be very different for different kind of forms - ie. in XForms the form only needs to make one check against corresponding XML Schema (you don't define rules in PHP). And you may choose not to use validation at all in which case you don't have to load it's code.</p>

  11. Sep 01, 2006

    <p>BTW, is it possible to get Dale's response edited to remove the long lines that are causing horizontal scrolling?</p>

  12. Sep 01, 2006

    <p>Original comment posted by Dale M. at Aug 31, 2006 09:32:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    <?php

    protected var $form;

    protected function setDefaults()
    {
    $defaults = array(...);
    $this->form->setDefaults($defaults);
    }

    protected function addElements()
    {
    $this->form->addElement(...);
    // ...
    }

    public function buildAction()
    {
    $this->form = Zend_Form::factory(...);
    $this->addElements(); $this->setDefaults();
    // ...
    }
    ?>
    ]]></ac:plain-text-body></ac:macro>

  13. Oct 18, 2006

    <p>My comment concerns UC7: Error Handling.</p>

    <p>I don't like the error strings in a message array. I think it works if you're only working in 1 language but when you start to add new locals this will break down (IMO). I think the validator should have an associated view template, that can be overridden in the configuration parms. When an error occurs, this view template will be executed to present the error message. The only additional information that the validator would need to properly present the error message would be the "caption/label" for that field.</p>

    <p>For example:<br />
    (required validator template)<br />
    '<caption>' is a required field.</p>

    <p>(range validator template)<br />
    '<caption>' must be between <min> and <max>.</p>

    1. Oct 18, 2006

      <p>Hi Dale</p>

      <p>Currently the validator is being revised so that it returns terse messages ready for translation (e.g. is_required, is_email, is_regex etc...). Of course you can override these values with whatever you choose as it's ultimately up to you how you want to transform these messages. The example above shows one scenario, but one you describe could be handled like so:-</p>

      <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[

      Your controller
      ---------------------------------------------------------------------------------
      $form = new MyForm;
      $form->add('myfield')->addValidator(new Zend_Form_Validator_Required('rule_01'));
      $renderer = new Zend_Form_Renderer_Xhtml($form);
      $view->form = $renderer;

      Your view
      ---------------------------------------------------------------------------------
      <p><?php echo $this->myTranslate($this->form->myfield->getError()) ?></p>

      ]]></ac:plain-text-body></ac:macro>

      <p>So you would pass off all translation responsibility to another view plugin. Or perhaps you could even pre-process all the translation strings with a model before it even hits the view? Ultimately it's left up to the developer to handle these problems. We'll be following the progress of Zend_Translate to see how that or similar components could potentially be integrated as a renderer pre-processor.</p>

  14. Oct 19, 2006

    <p>I would like to see the abstract classes <code>Zend_Form_Generator_Abstract</code> and <code>Zend_Form_Renderer_Abstract</code> be renamed to <code>Zend_Form_Generator</code> and <code>Zend_Form_Renderer</code> respectively. The "_Abstract" portion of the class name is redundant as the classes are already declared so using the PHP <code>abstract</code> keyword.</p>

    1. Oct 19, 2006

      <p>The framework as a whole should be consistent. Either all abstract classes are named Zend_XXX_Abstract or none of them are. In this proposal, there is a mix which is confusing. </p>

      1. Oct 19, 2006

        <p>I'm personally happier to use the explicit 'Abstract' suffix as it makes code more readable and, as Rob suggests, more consistent across the framework. We'll be cleaning up the structure as we go, but we're still in the middle of reorganising the structure so have not yet had the opportunity to update the proposal skeleton. Shan't be too far away, though!</p>

  15. Nov 25, 2006

    <ac:macro ac:name="unmigrated-wiki-markup"><ac:plain-text-body><![CDATA[I really agree with every thing that has been said by Michael Minicki (Martel).

    So my $0.2

    Form business model is only holder for field name values and we should have something like Zend_Form_To (Transfer Object or Token ) for that purpose.

    Zend_Form shoud only deal with form business and not validation witch is part of form logic flow. It could receive as a parameter a instance of Zend_Form_To to populate an auto generated form for example.

    Form Logic flow should be handled by a Form_Controller or Transaction_Controller (see here for example of php4 Transaction Engine http://www.interaktonline.com/Documentation/MXKollection/060000_tng3_core.htm)

    I did a dirty prototype with a Zend_Form_To and a Zend_Transaction here is example of what came up with :

    Example base on a Use case where a user is updating his user profile. The other neat thing about Transaction_Controller is that it make thing easier for code reuse, a insert transaction could share most of the call back function. Note I have put the callback function at the bottom for better readability.

    public function editAction()
    {

    ...

    // validator
    $validator = new Zend_Validator();
    // Form transfer object (holder for named values)
    $form = new Mmx_Form_To;
    // errors message
    $errors = '';

    // create a new transaction
    $transaction = new Zend_Transaction;
    // the transaction will start on form submit
    $transaction->registerTrigger('STARTER', 'DEFAULT', isset($_POST['add']));
    // If the transaction doesn't start the INIT triggers are execute
    // here we init form data
    $transaction->registerTrigger('INIT', 'triggerSetupForm', $form, $this->_getParam('id_pst'));

    // The transaction did start all the triggers are executed in the right order

    // validate form data
    $transaction->registerTrigger('BEFORE','triggerValidate', $validator);
    // Save data to the database inside the main transaction
    $transaction->registerTransaction('transactionSave', $form);
    // Save the picture to the file system
    $transaction->registerTrigger('AFTER','triggerSavePicture', $form);
    // Send a email to admin
    $transaction->registerTrigger('AFTER','triggerSendNotification', $form);

    // All transaction have been executed without errors
    // Redirect to a other page
    $transaction->registerTrigger('END','triggerRedirect');

    try

    Unknown macro: { $transaction->execute(); }

    // If one of the trigger throw a exception the transaction is stopped
    // we could implement some rollback technique to discard database change
    // the form is redisplay with a error message
    catch(Zend_TransactionException $ex)

    Unknown macro: { $errors = $ex->getMessage(); }

    // Pass form data to the view
    $view->form = $form;
    // Pass validator to the view for display field errors if any
    // and to view helper to handle client side validation with javascript
    $view->validator = $validator;
    // Main error message
    $view->errors = $errors;

    ...

    echo $view->render('FormView.php');

    ///////////////////////////////////////////////
    // Triggers

    function triggerSetupForm($form, $id)

    Unknown macro: { $profile = new UserProfile(); $data = $profile->find($id)->toArray(); $form->populate($data); }

    function triggerValidate($form)
    {
    $form->populate($_POST);
    $isnullrule = new Zend_IsNull();
    $validator->addRule('name', $isnullrule, 'please enter your name');
    $validator->addRule('surname', $isnullrule, 'please enter your surname');
    $validator->addRule('email', $isnullrule, 'please enter an email address');
    $validator->addRule('email', new Zend_Rule_Email(), 'not a valid email address');
    $validator->addRule('age', new Zend_Rule_Range(1, 150), 'number not in range 1-150');
    if (!$validator->isValid($form))

    Unknown macro: { throw new Zend_TransactionException('Errors in you form'); }


    }

    function transactionSave($form)

    Unknown macro: { $profile = new UserProfile(); $profile->save($form->toArray()); }

    function triggerSavePicture

    Unknown macro: { // save picture here // We throw a exeption if we can't save the picture // then the save to database shoud be rool back ! }

    function triggerSendNotification

    Unknown macro: { $mail = new Zend_Mail(); $mail->setBodyText('This is the text of the mail.'); $mail->setFrom('somebody@example.com', 'Some Sender'); $mail->addTo('somebody_else@example.com', 'Some Recipient'); $mail->setSubject('TestSubject'); $mail->send(); }

    function triggerRedirect()

    Unknown macro: { header("Location}

    // End Triggers
    ///////////////////////////////////////////////

    }

    Unknown macro: {/CODE}

    ]]></ac:plain-text-body></ac:macro>

    1. Nov 25, 2006

      <p>Ahhhhhhh ! How can I correct my comment? Sorry for this bad presentation. </p>

      1. Feb 14, 2007

        <p>I agree to separate form model datas and view presentation...</p>

        <p>With the logic of Zend framework you can do also this use case:</p>

        <p>updateAction(){</p>

        <p>$id = $this->_getParam('id');<br />
          <br />
          $fpost = Zend::registry('fPost');<br />
          $datas = array();<br />
          $datas['name'] = $fpost->getRaw('name');<br />
         $datas['email'] = $fpost->isEmail('email')</p>

        <p> </p>

      2. Feb 14, 2007

        <p>Sorry, I have made an error validation and I can't rectify...</p>

        <p>I agree to separate form model datas and view presentation...</p>

        <p>With the logic of Zend framework you can do also this use case:</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        public function selectAction()
         

        Unknown macro: {  $id = $this->_getParam('id');  $this->view->formdatas = $this->productTable->find($id)->toArray();        echo $this->view->render('form.php'); }

        public function updateAction(){
            $fpost = Zend::registry('fPost');
            $row = $this->table->find($this->_getParam('id'));
            $datas = array();
          
            try

        Unknown macro: {        if(FALSE === $fpost->isemail('email')) throw new Zend_Exception('invalid mail') ;        $datas['email'] = $fpost->getRaw('email');        $datas['name'] = $fpost->getRaw('name');        $row->setFromArray ($datas);        $row->save();    }

        catch (Zend_Exception $e)

        Unknown macro: {        $this->view->error = $e->getMessage();    }

           
            $this->selectAction();
        }
        ]]></ac:plain-text-body></ac:macro>

  16. Feb 23, 2007

    <p>in a nutshell, my opinion is that there should be both a "basic" and "advanced" approach to creating forms.</p>

    <p>Zend_Form_Basic:<br />
    This would be more or less be a QuickForm clone. I don't think there is anything necessarily wrong with a QuickForm clone since it can handle many of the common cases. Sure, it might be more tightly coupled with the the view/renderer/blah but this is about <em>automating</em> the creation of forms and minimizing any design effort.<br />
    Goal: be easy to use, automate creating forms</p>

    <p>Zend_Form_Advanced:<br />
    If you want a more fine-grained approach for how to lay out the form (more designer/flexible/friendly). You would get something like Simon Mundy's describes in his post on Aug 29, 2006 06:14 or something similar to Ralf's post on Aug 31,2006 05:48.<br />
    Goal: offer the flexibility that would be needed for more clear separation and flexibility</p>

    <p>I believe having two separate components for both basic and advanced usage will satisfy the different needs that would be required for a typical web developer. I'm skeptical if any kind of real middle ground can be reached for handling forms.</p>

  17. May 31, 2007

    <p>I think there should be clear separation between behavioural aspect of the form and its elements - such as validation, state, etc. and visual representation of the form elements. To the point that I could use form mechanism for form validation, while drawing my form by other means - such as pure HTML or template or any other. There should be also mechanism for each element to execute its validator and if there's a problem to know what's wrong with it. There should be also possibility to somehow define rules for more than one element (maybe just define callbacks to be called on validation). This would be one layer. <br />
    On top of this layer we may have other (optional) layers which would provide means to display form elements, to manage their lifecycle (e.g. remember data between calls) and to link them to the MVC infrastructure if needed. </p>

    <p>Also we might want to consider supporting some security measures against XSRF replay attacks - i.e. generating some secret value for the form when displayed, storing it in the session and then checking it when submitted, so that if somebody else submits the same form it would not work. </p>

  18. Jun 01, 2007

    <p>I'm from the opinion that it is possible to make a cake and eat it too.</p>
    <ul>
    <li>Zend_Form
    <ul>
    <li>Contains business logic and everything related to data</li>
    </ul>
    </li>
    <li>Zend_Form_Session
    <ul>
    <li>Manages form data between submissions via handlers (serializing / db writes / etc.)</li>
    <li>Allows for submission tracking
    <ul>
    <li>guarding against multiple submits possible</li>
    <li>XSRF replay attacks prevented</li>
    <li>no cookie or special end-user means of tracking necessary (form session may be tied to PHP session)</li>
    </ul>
    </li>
    </ul>
    </li>
    <li>Zend_Form presentation classes to extend Zend_Form
    <ul>
    <li>Zend_Form_XHTML</li>
    <li>Zend_Form_XForm</li>
    <li>Zend_Form_AJAX (may extend Zend_Form_XHTML?)</li>
    <li>Zend_Form_Paged (multiple pages)</li>
    <li>Zend_Form_Tabbed (multiple tabs on same page using AJAX)</li>
    </ul>
    </li>
    </ul>

    <p>Therefore, if you like a business model for handling form but not actually rendering a form, Zend_Form and Zend_Form_Session are for you.</p>

    <p> However, if you're like me, you may appreciate the ability to render a form (or parts of it) using the respective presentation classe above. </p>

    1. Sep 05, 2007

      <p>I would go this way too. One simple solution could be like this :</p>

      <ul>
      <li>Zend_Form is just containing data between request.</li>
      <li>Validation and filtering is delegated (proxy?) to a Zend_Input_Filter instance</li>
      <li>Validation rules are pass to Zend_Form as an array (as specified in the Zend_Filter_Input documentation). This array could be reuse on the view to generate client side validation.</li>
      </ul>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $form = new Zend_Form();

      $form->setDataSource($_POST);

      // set filters and validations rules
      $form->setValidationRules(null, $validators);

      // failed
      if ($form->hasInvalid() || $form->hasMissing()) {
      $this->view->errors = $form->getMessages();
      }
      // succeed
      else {
      // handle data
      }
      ]]></ac:plain-text-body></ac:macro>

      <p>In the view part you can use plain xhtm or zend form view helpers and retrieve data from Zend_Fom</p>

      <p>OR</p>

      <p>Use Zend_Form_Xhtml (or Zend_Form_Render_Xhtml ) solution which could render the form elements, errors and hits. </p>

  19. Jul 30, 2007

    <p>Based on this proposal and a discussion at #zftalk a few weeks back I started my own implementation of Zend_Form.<br />
    Today I placed it on a SVN server so everyone can have a look and provide me with much needed comments.</p>

    <p>URL: <a href="http://tools.assembla.com/svn/zfcomponents/">http://tools.assembla.com/svn/zfcomponents/</a></p>

    <p>Please beware that I'm working on the component at the moment of this writing, so it may be possible there are some unexpected bugs. The examples that are provided also need some hacking at this moment to get them to work (bad naming in the examples). Will fix that ASAP <ac:emoticon ac:name="smile" /></p>

  20. Sep 05, 2007

    <p>Your solution could be simplified by delegation all the validation and filtering stuff to a Zend_Input_Filter instance. Validation rules are pass to Zend_Form as an array, as specified in the Zend_Filter_Input documentation or directly with a Zend_Filter_Input instance.</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $form = new Zend_Form();

    $form->setDataSource($_POST);

    // set filters and validations rules
    $form->setValidationRules(null, $validators);

    // failed
    if ($form->hasInvalid() || $form->hasMissing()) {
    $this->view->errors = $form->getMessages();
    }
    // succeed
    else {
    // handle data
    }
    ]]></ac:plain-text-body></ac:macro>

    1. Sep 05, 2007

      <p>Sorry this comment was intend to Mitchell Hashimoto Zend_Form proposal... <br />
      There is too many of them <ac:emoticon ac:name="smile" /></p>