Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="toc"><ac:parameter ac:name="minLevel">2</ac:parameter></ac:macro>
<p>Zend_Form has been accused of violating the principal of separation of concerns, due to the fact that it has Model-related logic (filtering and validation, metadata), as well as View-releated logic (rendering, decorators).</p>

<p>While Form objects may be used to provide validation to domain models, many do not like this linking of concerns, and would prefer the ability to attach validation chains from models to the form in order to provide validation error hinting; at the same time, many others feel that forms as simply collections of elements with no ability to validate makes them basically worthless.</p>

<p>Finally, the decoration system, while powerful and flexible, is also quite difficult for many to learn. Having it coupled to Zend_Form causes some issues, as it basically inverts the decorator principal, and is somewhat misnamed as it primarily acts as a filter chain.</p>

<h2>Recommendations</h2>
<h3>Refactor Form view helpers to accept form/element/group objects</h3>
<p>Currently, we use the ViewHelper decorator with most form elements as the first decorator. While this works well, it also complicates the issue when you want to build your markup manually; you are forced to use the ViewHelper decorator if you want to use a view helper to render the element.</p>

<p>One simple way to solve this is to modify the individual <code>form*()</code> view helpers to accept elements (or other Zend_Form objects), then we can simplify things greatly. As an example:</p>

<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
$element->setOptions(array(
'size' => 25,
'maxlength' => 140,
'class' => 'form-text',
));
echo $view->formText($element);
]]></ac:plain-text-body></ac:macro>

<h3>Use PubSub as basis for Decorator Chains</h3>
<p>If we use the pubsub's <code>filter()</code> method, we can achieve the same effect as the current decorators. As an example:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
// Assuming zend\form\DecoratorChain extends pubsub\FilterChain, and that
// render() proxies to filter():
$chain = new zend\form\DecoratorChain();
$chain->subscribe('zend\form\decorator\Label');
$chain->subscribe('zend\form\decorator\ViewHelper');
$chain->subscribe('my\decorator\Div');
$chain->setView($view);
echo $chain->render($element);
]]></ac:plain-text-body></ac:macro>
<p>We would provide some pre-formulated chains as part of this initiative. This would then entail simply setting the view and passing in the element.</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
$chain = new zend\form\decorator\DefinitionListChain;
$chain->setView($view);
echo $chain->render($element);
]]></ac:plain-text-body></ac:macro>

<p>The above promotes re-use of decorator chains with multiple elements, and also re-use of pre-defined chains.</p>

<p>The actual act of rendering would then be removed from <code>Zend_Form</code> itself.</p>

<h3>Use PubSub as basis for Filter and Validation Chains</h3>
<p>If we use the pubsub's <code>filter()</code> method, we have all the functionality of the current <code>Zend_Filter</code> and <code>Zend_Validate</code> chains. This can allow us to detach chains or attach chains. As such, we would define chains and attach them to the form elements.</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
$vChain = new zend\validator\ValidatorChain();
$vChain->subscribe('Int');
$vChain->subscribe('MinLength', array(3));
$vChain->subscribe('MaxLength', array(20));
$vChain->breakOnFailure(true); // stop validating on first subscriber failure
$element->setValidatorChain($vChain);

$fChain = new zend\filter\FilterChain();
$fChain->subscribe('StringTrim');
$element->setFilterChain($fChain);
]]></ac:plain-text-body></ac:macro>
<p>This allows us to continue to perform validation and filtering as before, but offloads much of the code and functionality to other, reusable components.</p>

<h3>Allow retrieving and setting all element validators and filter chains</h3>
<p>In order to achieve full separation, we would need the ability to retrieve these for the entire form for re-use in Models to validate data sets, as well as to pull from Models in order to attach to Forms. In essence, we're talking about an update to <code>Zend_Filter_Input</code>.</p>

<p>The basics would work as follows:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
// Retrieve filter and validator chains for all elements in form
$filterChain = $form->getFilterChain();

// Attach to model:
$model->setFilterChain($filterChain);
]]></ac:plain-text-body></ac:macro>

<p>The object structure would look as follows:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
zend\FilterChain::__set_state(array(
"foo" => zend\filterchain\Element::__set_state(array(
'filterChain' => zend\filter\FilterChain(array(
'_subscribers => array(
'StrimTrim',
),
)),
'validatorChain' => zend\filter\ValidatorChain(array(
'_subscribers => array(
array('Int'),
array('MinLength', array(3)),
array('MaxLength', array(25)),
),
)),
)),
))
]]></ac:plain-text-body></ac:macro>
<p>and would be used (roughly) as follows:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
$chain->isValid($values);
$value = $chain->get($key);
$chain->set($key, $value);
$chain->setAll($values);
$elementChain = $chain->getChain($key);
]]></ac:plain-text-body></ac:macro>

<h3>Make the metadata/behavior separation explicit</h3>
<p>The various classes in <code>Zend_Form</code> basically contains metadata and behavior. The metadata is typically consumed by decorators in order to determine how to render themselves; the behavior is generally related to validation and/or error message retrieval (which is a related task).</p>

<p>As such, we propose that all Form classes will define a "metadata" property that will contain key/value pairs, and a set of setter/getter methods for the metadata (with specific setters for metadata that requires normalization).</p>

<p>As an example:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
$form->setMetadata(array(
'action' => $url,
'method' => 'post',
'id' => 'registration',
));

$element->setMetadata(array(
'class' => 'form-text',
'size' => 25,
'maxlength' => 140,
));
$element->setName('foo');
]]></ac:plain-text-body></ac:macro>

<h3>No IDs by default</h3>
<p>Currently, the various <code>Zend_Form</code> elements all generate IDs. With modern JS libraries, this is typically unnecessary, and having explicit IDs makes it very difficult to have forms with variable numbers of the same element or group of elements. Removing ID generation would solve a number of UI issues. (Note: IDs could be set manually as metadata; alternately, <code>setName()</code> could be overridden in order to set the ID as well.)</p>

<h3>Translation</h3>
<p>Translation should be moved to the view layer. The View and Decorator chains would receive the Translator object and use it to translate appropriate labels and metadata. As such, the form, its elements, and the individual validator and validator chains would need no such knowledge of this information.</p>

<h2>BC Concerns</h2>
<h3>Configuration</h3>
<p>Since the chains would be separate objects, and the interaction with those chains would no longer be part of the various Form objects, creation of the chains from configuration will no longer be possible.</p>

<p>One way to mitigate this would be to have a "form builder" class that can build the Form objects and all related objects from configuration. Decorators would be one of the exceptions to this, as the Decorator chains would no longer be contained within the various Form objects. As such, a "decorator chain" builder could be useful.</p>

<h3>Metadata</h3>
<p>If metadata is moved to an explicit "metadata" container, this may cause problems with existing configuration. A legacy builder class could alleviate this problem, however.</p>

<h3>Removal of IDs</h3>
<p>Removing IDs may have UI implications. In particular, the Dojo integration relies heavily on the IDs in order to work. As such, this feature may need to be configurable.</p>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Nov 17, 2009

    <p>There's one thing that I really would like to see in Zend_Form 2.0, and that is support for a non-indexed array notation in the element names. Example:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    <input type="text" name="credentials[][username]" value="foo" />
    <input type="text" name="credentials[][username]" value="bar" />
    <input type="text" name="credentials[][username]" value="baz" />
    ]]></ac:plain-text-body></ac:macro>

    <p>Which would be received on the PHP side as:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    // Using $_POST directly only for demonstration purposes
    $_POST['credentials'] = array(
    array('username' => 'foo'),
    array('username' => 'bar'),
    array('username' => 'baz')
    );
    ]]></ac:plain-text-body></ac:macro>

    <p>This feature would make it easy to support dynamically added fields using JS. Currently such a setup requires creative coding that can easily be avoided when using this notation.</p>

    1. Nov 17, 2009

      <p>This is a huge part of the reason behind not requiring IDs – by not requiring unique IDs, this becomes more possible to support.</p>

    2. Nov 20, 2009

      <p>That would be so nice. Currently, I am not adding form elements created by JS to Zend_Form. </p>

      <p>Support for non indexed array can be a huge help here.</p>

    3. Nov 20, 2009

      <p>That would be so nice. Currently, I am not adding form elements created by JS to Zend_Form. </p>

      <p>Support for non indexed array can be a huge help here.</p>

    4. Mar 30, 2010

      <p>See my Array Notation related <ac:link ac:anchor="comment-21266847"><ac:link-body>comment</ac:link-body></ac:link> down the page.</p>

  2. Nov 17, 2009

    <p>I strongly agree with Jurrien; this is a critical feature. Zend_Form is absolutely brilliant but one of the areas it doesn't support well is JS type stuff. I'd love to see some sample/rough code to suggest how multiple elements and dynamically added form elements might be supported in 2.0.</p>

    <p>What's the attraction to using chains here (excuse my ignorance) and will they still support features like breakOnFailure? Further, are there any features of Zend_Form 1.0 that won't be supported in the new version?</p>

    1. Nov 17, 2009

      <p>I'll get some code examples up in the coming days to illustrate how dynamically added form elements might be supported. While eliminating mandatory IDs helps solve part of the problem, there are additional aspects that need to be addressed.</p>

      <p>The reason for using chains is to eliminate coupling between Zend_Validate and Zend_Form. Yes, breakOnFailure is supported – it's a specific use case of the Phly_PubSub's publish functionality (see the publishUntil() method in the Provider class). Furthermore, this functionality is abstracted sufficiently to be useful in a variety of components, making chains trivially simple to create and use – and providing a consistent methodology to do so.</p>

      <p>Regarding existing features: I don't see any existing features that won't be supported; there will be features that will need to be done in a different way, but not removed.</p>

      1. Aug 13, 2010

        <p>This would be amazing. Than input elements could be cloned to allow for a variable amount of elements. What are the additional aspects that need to be addressed?</p>

  3. Nov 20, 2009

    <p>here are my thoughts on a very general refactoring of Zend_Validate, Zend_Filter and such in combination with chains and the separation of technical and domain validation, and more importantly why this is required to make Zend_Form much more powerful.</p>

    <p>1. Zend_Validate should be refactored to allow for stateless validations, which would allow to instantiate only one validator per type and could hugely optimize performance. For this Zend_Validate_Result should be introduced that acts as a stack for validations that failed with their respective error messages.</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $result = new Zend_Validate_Result();
    $validator = Zend_Validate::factory('MaxLength');
    $validator->accepts($value, $options, $result);
    if(!$result->isValid()) {
    var_dump($result->getMessages());
    }
    ]]></ac:plain-text-body></ac:macro>

    <p>For this we could introduce a new interface Zend_Validate_Stateless and make sure that the factory creates only instances of this type.</p>

    <p>2. Zend_Filter should allow stateless filtering also.</p>

    <p>3. There should be Aggregates of both Filters and Validators, Zend_Validator_Aggregate and Zend_Filter_Aggregate that are initially subtypes of a new Zend_Filter_Input for their respective type. They define several "value" => filter/validation rules.</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $filterAggregate = new Zend_Filter_Aggregate();
    $filterAggregate->addFilter('fieldA', $filter);

    $validateInput = new Zend_Filter_Aggregate();
    $validateInput->addFilter('fieldA', $intValidator);
    $validateDomain->addFilter('fieldA', $domainValidator);
    ]]></ac:plain-text-body></ac:macro>

    <p>4. There should be methods to merge aggregates into each other.</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $inputFilter = new Zend_Filter_Input();
    $inputFilter->attach($filterAggregate);
    $inputFilter->attach($validateInput);
    $inputFilter->attach($validateDomain);
    ]]></ac:plain-text-body></ac:macro>

    <p>5. Each kind of Aggregate signals all its respective children chains (be it validator or filter), so Aggregate -> Chain -> Specific Validator/Filter.</p>

    <p>6. You can attach aggregates to Zend_Form instances:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $form->addInputFilterValidator($inputFilter);
    ]]></ac:plain-text-body></ac:macro>

    <p>7. Internally in Zend_Form calls to setValidators setFilters and such would proxy to the attached filtering/validation aggregate, i.e. it must be passed as a dependency to all elements and subforms of a form, they all hold the one instance of the aggregate per Form.</p>

    <p>8. If no Input Validator/Filter is set a new one is created, if then one is attached to the Form it should be merged with the existing one. This also applies to cases were different existing forms are stuck to each other (Form <-> Subform).</p>

    <p>9. Currently its very hard to move dependencies through the complete Zend_Form structure. Maybe we should go the DOMDocument way and allow to add only elements or subforms that have been created to a factory method on the Zend_Form instance? This would also solve various plugin loader dependency problems.</p>

    <p>Benefits:</p>

    <ul>
    <li>Stateless allows to cut the number of objects used for filtering and such to a very low number.</li>
    <li>Complete Separation between validation, filtering and the form aspect.</li>
    <li>New view on input: It always comes in aggregates, there is no value which is standing alone and is being filtered. There are always many different values that need to be validated in sequence or even with dependencies.</li>
    </ul>

  4. Nov 29, 2009

    <p>Great suggestions!</p>

    <p>I was dreaming for some time of the elements, validators, filters and decorators separation.<br />
    Currently there are some forms in my system with about 150 fields on each. Of course, they consist of some subforms. Also these forms use custom view-script decoration. It's hard to maintain and change each element decoration/validation rules. I believe the new approach will make this work easier.</p>

    <p>One of the forms may be subform in the other forms. And it's validation rules often change depending on the main form. I think "Aggregate" approach is rather complicated but it would provide easy whole form behavior change.</p>

  5. Dec 16, 2009

    <p>I have one suggestion too. Make it possible to handle each option of Zend_Form_Element_Multi as separate object. Or at least make options "unescapable". Making things like radio button list with name and description for each option includes great deal of pain. Use case is transport selection in eshop, where you need to name the option (FedEx), show the price ($5) and also add some limitations for example (only for orders below $5000). It would be great to have sth like:</p>

    <ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
    $this->setDecorators(
    'viewHelper' => array('optionDecorators' => array('Label', 'Description')),
    'Label',
    'Description',
    );
    ]]></ac:plain-text-body></ac:macro>

    1. Dec 16, 2009

      <p>I would argue that this is a job for a custom element and/or view helpers, and not the place of ZF to accommodate. ZF should be providing the minimal code that covers the bulk of use cases, while being flexible enough that other use cases can be easily provided by extension or implementing interfaces.</p>

  6. Dec 19, 2009

    <p>What about efforts towards making Zend_Form lighter and easier to use?</p>

    <p>For starters lets move everything related to rendering out of the Zend_Form class, including managing decorators, which could go in a specialized registry. Then perhaps add a method to the Zend_Form class to assemble a transfer object which can be used for separate rendering, e.g.:</p>

    <p>$to = $form->getTransferObject();</p>

    <p>$formView->assign('form', $to);</p>

    <p>$formView->setScript('foo.phtml'); //proposed method that allows calling of render() without arguments</p>

    <p>$this->view->assign('fooForm', $formView); //Zend_View should have a __toString() method which renders the view provided a script has been set.</p>

    <p>This still uses Zend_Form for building the spec, validation and filtering, but allows rendering using a completely custom template (without the need for building complex decorator structures).</p>

    1. Dec 19, 2009

      <p>This is actually what this page is already proposing. To clarify:</p>
      <ul>
      <li>Validator chains would be separate objects, allowing you to have these attached to your model, and then attach them to the form merely for purposes of error reporting and/or value retrieval. This allows you to have a pure validation scheme for your models that is completely independent from the form objects; it also allows you to re-use validators and validation chains between elements easily.</li>
      <li>To render, you would pass your form and/or elements to decorator chains, which would be completely separate objects.<br />
      In this latter vein – there is absolutely nothing forcing you to use decorators now or in the future. You can always pull information from the elements discretely in order to build your markup (in fact, that's all the decorators are doing). Decorators simply automate this process and help to keep your view scripts more readable.</li>
      </ul>

      1. Dec 19, 2009

        <p>I see. I don't think I like the idea of using publish-subscribe for building a decorator chain though. It feels off in semantics, what is the topic they are subscribing to? Wouldn't it be more appropriate to stick with something of a Composite?</p>

        <p>While on the topic of composites, I second Benjamin's call for aggregate validators and filters (and add I would think this more appropriate for the current decorators as well). </p>

        <p>Something else I'd like to suggest is context-based validation, for example validation of a ZIP. You'd attach validators assigned by the value of a set index in the context and validity would be determined by the validators that matches the value. In the example of a ZIP, you could set "country" as the key, and assign different validator chains for values "US" and "CA", and optionally a default chain used when the value in the context has no specific validators. With 5.3 this becomes even more interesting as you can easily pass a closure instead of a string or regular expression to match.</p>

        <p>Of course this is conditional use, thus fundamentally different to "chains".</p>

        1. Dec 19, 2009

          <p>Actually, there are two pieces to the Phly_PubSub component I've been using to prototype 2.0 features. In the first, obviously, it's a publish-subscribe system. In the second, it's used as a filter chain (this is similar to how such components are done in other frameworks and event-driven architectures). Phly_PubSub has two approaches to this latter: you can use topics, or you can have a topic-less filter chain. In the case of decorators, they'd most likely be topic-less – though we could potentially allow attaching any and all decorators to a single pubsub provider under topics such as "form", "display-group", "element-text", "element-multi", "element-button", etc, and thus get maximum re-use from a single decorator chain.</p>

          <p>I like the idea of conditional branching in chains, but it's really, really difficult to achieve cleanly and still keep performance. I'm still interested in investigating it, however.</p>

          1. Dec 20, 2009

            <p>It's partly just semantics, but also I think a more specific data structure would be more appropriate (Golden Hammer?). On a side note I never quite understood why element decorators are labelled as such, it is certainly not a traditional implementation of the Decorator pattern as described in the GoF, for that decorators would have to share a type with elements, defining the interface for render(). I digress.</p>

            <p>What I would like to propose for "decorators", filters and validators alike, is using an aggregate chain instead of a list. Every object has a child, like in a Chain of Responsibility (and with break on error it would very much behave like one). Add in a junction type which will be able to hold several chains (this '''would''' use a list) and you have a recipe for a very flexible yet rigid data structure. You can branch to aggregate chains depending on the implementation of the junction which would determine the condition. Performance loss depends on the condition in the concrete junction: for example a simple hashmap lookup should cause no measurable performance loss at all.</p>

            <p>Limiting to validators only for a sec, because it has such an obvious usage example, this could look something like this (please pardon the absence of multiplicity):</p>

            <p>EDIT: I just noticed there's an aggregate relation missing between ValidatorJunction and ValidatorAbstract. You get the idea.</p>

            <p><ac:image><ri:attachment ri:filename="zend_form.png" /></ac:image></p>

            <p>Usage example using the ZIP example and context value based junction:</p>

            <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
            $zipElement->setValidator(new ContextJunction(
            'country',
            array(
            'US' => new NotEmptyValidator(
            new RegexValidator('/^(\d

            Unknown macro: {5}
            \d
            Unknown macro: {9}
            \d

            -\d

            Unknown macro: {4}

            )$/')
            ),
            'CA' => new NotEmptyValidator(
            new RegexValidator('/^[a-z]\d[a-z]\s?\d[a-z]\d$/i')
            )
            ),
            new StringLengthValidator(4)
            ));
            ]]></ac:plain-text-body></ac:macro>

  7. Dec 27, 2009

    <p>Hi,</p>

    <p>How about types of filters on 2.0 ?</p>

    <p>I suggest to have actually 3 types of filters (one was proposed for 2.0 but didn't heard much about them).</p>

    <p>I tried to explain this on <a class="external-link" href="http://framework.zend.com/issues/browse/ZF-8130">http://framework.zend.com/issues/browse/ZF-8130</a></p>

    <p>We need basically three types of filters on Zend_Form:</p>

    <ul>
    <li>rendering filter</li>
    <li>pre-validation filter (existing filters)</li>
    <li>post-validation filters (proposed for 2.0)</li>
    </ul>

    <p>One sample:</p>
    <ul>
    <li>a field into the model has the one date stored as timestamp</li>
    <li>i get the record from the model</li>
    <li>i populate the form with the record data</li>
    <li>at rendering the RENDERING FILTER is transforming the date to a localized format: mm/dd//yyyy or so and it displays into the text field the date into this format</li>
    <li>user is making the adjustements to the data (including date) and it saves the form</li>
    <li>before validation, we are filtering using some NORMAL (current filters of Zend_Form) filters, let's say for StripTags, Trim, aso</li>
    <li>validation is checking that the data is into mm/dd//yyyy format</li>
    <li>after validation, the NEW FILTERS PROPOSED FOR 2.0 are changing the data back to timestamp, from mm/dd//yyyy format</li>
    <li>the data is saved to the model</li>
    </ul>

    1. Dec 31, 2009

      <p>The changes proposed actually negate the need for or possibility of rendering filters, as forms would not be responsible for rendering themselves; your decorator chain would take care of this. As one example, the first decorator filter in your chain could simply alter the element value to the appropriate format, and that value would then be decorated. As for post-validation filters, this is really the role of the domain model, not the form. As such, you could very easily simply attach a different filter chain to the form within your model (since filter chains would be separate objects under this proposal).</p>

      1. Dec 31, 2009

        <p>Related to rendering filters. How are supposed to be attached filters to decorators ?</p>

        <p>Of course, i can create a custom decorator instead of ViewHelper decorator by example and allow as options an option for filter/filter chain. But i think this would be better to be directly into trunk components, and not into an "extra"/own library...</p>

  8. Jan 03, 2010

    <p>Reusing the pubsub component for validator/filter chains is a nice idea. However from an usage point of view, a method called "subscribe()" is not intuitive for adding a new filter to an element. </p>

    <p>I'd rather have "add()". Certainly for people who don't know their PoEAA backwards, it would be clearer when reading the code.</p>

    <p>Regards, </p>

    <p>Rob...</p>

    1. Jan 29, 2010

      <p>I agree, just because we use PubSub doesnt mean the methods have to match those in GoF. they should be specialized to the domain, being form rendering.</p>

  9. Jan 29, 2010

    <p>I propose a refactoring of the underlying data-structure of Zend_Form, since its missing a concept.</p>

    <p>What people always complain about:</p>

    <p>1. Its hard to group fields together that have dependencies on each other<br />
    2. Its hard to get many fields that represent one value.<br />
    3. The decorator chain is to linear for certain use-cases<br />
    4. Radio and Checkbox Groups cant be rendered as parts.<br />
    5. Its not that easy to render a form inside a html script and place the elements freely.<br />
    6. Its annoying to configure decorators (wanting to change something => reconfigure EVERYTHING).</p>

    <p>My solution (and i am implementing a prototype).</p>

    <p>1. Separate the concept of "Field" and "Fieldset" that are hidden inside the Zend_Form_Element<br />
    2. Each Field can have many Elements.<br />
    3. Elements implement a very simple interface Zend_Form_Element<br />
    4. Decorators implement Zend_Form_Element<br />
    5. Each element may have decorators (or not).<br />
    6. Each element has 0:n child elements.<br />
    7. Each element has 0:n child fields (as a fieldset).<br />
    8. Form and Subforms are elements<br />
    9. There are Select, Radio and Checkbox Elements where the options are elements themselves. For large select/radio/checkbox sets, there are elements where they are only options. (Performance vs Ability to place elements freely!)</p>

    <p>Sounds more complex? But its more simple as "decorators" are not needed anymore by default. Why?</p>

    <p>1. "Label", "Description", and "Errors", "ViewHelper" are Elements of a "Default" Field<br />
    2. Fields and Elements implement __invoke(), which proxies to setOptions.<br />
    3. Each field and each element must unique in its context, they can be accessed by __get($name) or getField($name)/getElement($name).<br />
    4. By default the elements of a field can be rendered in a specified order to emulate the Zend Form 1.x behaviour<br />
    5. All fields/elements/decorators have to be created through factory methods on the form so that dependencies are always shared and passed between the elements.</p>

    <p>Examples:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $view = new Zend\View\PhpView();
    $options = array('view' => $view', 'script' => 'myForm.phtml');
    $form = new Zend\Form\Form($options);
    $field = $form->createField('birthday');
    $field->addElement('text')>setLabel('Foo')>setDescription('Bar');
    ]]></ac:plain-text-body></ac:macro>

    <p>In script:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    <?= $this->form; ?>
    <h4><?= $this->birthday->label; ?></h4>
    <?= $this->birthday->errors; ?>
    <p><?= $this->birthday->element; ?> (<small><?= $this->birthday->description; ?></small>)</p>
    </form>
    ]]></ac:plain-text-body></ac:macro>

    <p>Or if the $form is rendered without script, it does so by going the decorator approach and a pre-defined order of the elements. The render method of each element looks like this:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    public function render($content='')
    {
    $myOwnContent = $this->renderMyself();
    // APPEND PREPEND, WRAP logic
    return $myOwnConntent . $content;
    return $content . $myOwnContent;
    return $myOwnContentPrefix . $content . $myContentPostFix;
    }
    ]]></ac:plain-text-body></ac:macro>

    <p>If as in the script before "$this->birthday->description"; is called for display, render is called with empty $content to decorate.</p>

    <p>Now we can decorate elements, the element gets a DatePicker:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $form->birthday->element->addDecorator('jQueryDatePicker', $options);
    $form->birthday->element->appendDecorator('jQueryDatePicker', $options);
    $form->birthday->element->prependDecorator('jQuerYDatePicker');
    $form->birthday->element->addDecorateAfter('jQueryDatePicker', $options, $afterDecoratorName);
    $form->birthday->element->addDecorateBefore('jQueryDatePicker', $options, $beforeDecoratorName);
    ]]></ac:plain-text-body></ac:macro>

    <p>And the label gets a tooltip:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $form->birthday->label->addDecorator('Tooltip', array('tip' => 'Blabla'));
    ]]></ac:plain-text-body></ac:macro>

    <p>We can also specify birthday as 3 input boxes, by adding 3 fields to a "valueGroup" element.</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $group = $form->birthday->addElement('valueGroup');
    $year = $fieldset->createField('year');
    $year->addElement('input');
    $month = $fieldset->createField('month');
    $month->addElement('input');
    $day = $fieldset->createField('day');
    $day->addElement('input');
    ]]></ac:plain-text-body></ac:macro>

    <p>now $form->birthday->getValue() will return an array of year, month, day. Unless you have filtered it to return only the date.</p>

    <p>Subforms work in the same way:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $subfield = $form->createField('sub1');
    $subform = $subfield->addElement('SubForm', array('partial' => 'subform.phtml'));
    $field = $subform->addField('interests');
    $field->addElement('radio', array('hockey' => 'Hockey', 'soccer' => 'Soccer'))
    ->setLabel('Interests')
    ->setDescription('Tell me your interests!');
    ]]></ac:plain-text-body></ac:macro>

    <p>This looks more verbose than Zend_Form v1, but convenience methods to the rescue:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $subForm = $form->createSubForm('sub1', array('partial', 'subform.phtml'));
    $subForm->createElement('radio', 'interests', array('multiOptions' => ..., 'label' => '', 'description' => ''));
    ]]></ac:plain-text-body></ac:macro>

    <p>On each Element you call:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $element->create[ELEMENTNAME]($fieldName, $options);
    ]]></ac:plain-text-body></ac:macro>

    <p>Which saves you talking to the "field value" level.</p>

    <p>Both Fields and Input-Elements can have Validators and Filters. An $field->isValid() collects all error messages and puts them onto the $field->errors element. This way you can validate several values in conjunction (when there are dependencies) and single primitive types from form input fields.</p>

    <p>Now to the funny parts, all Elements and Fields implement __invoke() which proxies to setOptions.</p>

    <p>Inside the view script, a designer can progressively enhance elements:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    <?= $this->form(array('id' => 'my-id')); ?>

    <h4><?= $this->birthday->label('Tell me your birthday please', array('class' => 'my-label')); ?></h4>
    ]]></ac:plain-text-body></ac:macro>

    1. Jan 30, 2010

      <p>gah, I prototyped this and its a bit too complex, i need another insight <ac:emoticon ac:name="smile" /></p>

      <p>Its either always placing all the elements manually, or having them "decorated" completly. A mix however is too complicated to configure.</p>

      <p>The problem I see is, that label, description and such stuff are "elements" themselves and are put to strict to the form control element. Thats why so many ugly decorators exist and so much logic about prepend, append, wrap and such has to be thought of.</p>

      <p>Zend_Form should describe the data-structure, for example the following complex thing:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $data = array(
      'user_id' => 1,
      'username' => 'beberlei',
      'emails' => array(
      0 => 'foo@example.com',
      1 => 'bar@example.com',
      2 => 'baz@example.com',
      ),
      'addresses' => array(
      0 => array(
      'street' => 'My Foostreet 1',
      'zipcode' => '12345',
      'city' => 'New York',
      'country' => 'US',
      ),
      1 => array(
      'street' => 'My Barstreet 2',
      'zipcode' => '54321',
      'city' => 'London',
      'country' => 'GB',
      ),
      ),
      );
      ]]></ac:plain-text-body></ac:macro>

      <p>Pressing stuff like description, labels and rendering ontop of the Data-structure is the most complex part. And the current Decorator implementation shows the complexity. I would like to see a refactoring towards something like JavaServer Faces, <a class="external-link" href="http://java.sun.com/javaee/5/docs/tutorial/doc/bnaph.html">http://java.sun.com/javaee/5/docs/tutorial/doc/bnaph.html</a></p>

      <p>Zend Form is relativly near to this, decorators are called renderers there (a much better name!) and you can combine elements and renderers freely (separation of concerns). However the displaying of the form happens inside HTML markup, i.e. a form consists of a "Zend_Form" implementation plus at least a partial script.</p>

      <p>My prototype had a Zend\Form\FormRegistry instance, which is a required second constructor argument. It holds all the plugin loaders, the view instance, translator and other important dependencies that have to be shared between all elements. This is imho a good approach to solve lots of dependency problems inside Zend_Form. I also used factory methods exlusively, no:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $element = new Zend_Form_Element_Text("foo", $options);
      $form->addElement($element);
      ]]></ac:plain-text-body></ac:macro>

      <p>anymore, since here we can't share dependencies in an efficient way.</p>

      <p>I will try another approach. The question I ask myself is, why are there decorators at all? There should be a view script and view helpers. The view helpers hold an instance of the current Zend_Form instance that is rendered.</p>

      1. Mar 24, 2010

        <p>Benjamin, i am not good at hypothetical explanations, but maybe <a href="http://framework.zend.com/issues/browse/ZF-9516">ZF-9516</a> could fit into your imaginations.</p>

  10. Jan 30, 2010

    <p>Ad. "Allow retrieving and setting all element validators and filter chains"</p>

    <p>Retrieving and setting the complete Validator or Filter chains is a nice to have, but its a very linear approach from model to view and enforces you to design a form exactly like the internal data-structure of the model. This is a violation of the separation of concerns principle.</p>

    <p>I would rather see a focus on the flexibility to transform model to form data-structure and back and only optionally use this feature when I develop an application that is so simple that model <-> view dependencies are not a problem.</p>

    <p>Ad. "Refactor Form view helpers to accept form/element/group objects"</p>

    <p>Using a config/registry object all inside Zend Form it would be possible to completly "remove" decorators by using a Zend_View instance that can "decorate" calls to view helpers.</p>

    <p>Say you don't want to customize the markup, so a call to the "form" view helper should not only render the <form> tag, but also all the elements inside. This can be done by extending the form view helper at runtime.</p>

    <p>However when you want to customize the markup all the "form elment" view helpers just need to render themselves. In the speak of Zend_Form there should be an immutable option on construct that defines how ALL elements of ALL types are decorated by default (i.e. loadDefaultDecorators()). This is what Decorator Chains here described do. There should not only be pre-defined chains, but also sets of chains.</p>

  11. Feb 24, 2010

    <p>I still have yet to get a clear explanation of why Zend_Form maintains 3 loaders for filters, validators, and decorators per element in 1.x. I imagine there are applications for this, but I think they are more of an edge case than how the majority of developers use Zend_Form, so having this approach be the default is puzzling. Even having Zend_Form use a single set of loaders per form by default would be a significant performance improvement for larger forms. It's not like the behavior couldn't be overridden to use separate loaders per element if a developer actually wanted that behavior. See <a class="external-link" href="http://matthewturland.com/2009/04/03/zend_form-and-zend_loader_pluginloader-snafu/">http://matthewturland.com/2009/04/03/zend_form-and-zend_loader_pluginloader-snafu/</a> for more information on how the current default behavior can be overridden, where I'd like to see that override be the default behavior in Zend_Form 2.0.</p>

  12. Mar 29, 2010

    <p>As some of you may have noticed in the Issue Tracker, i am delving into Zend_Form especially<br />
    ElementsBelongTo and belongsTo. And i think you would agree that this part is not intuitive.</p>

    <p>My suggestion in respect to Naming Formitems is: forget ElementsBelongTo and requiring unique <br />
    Names, instead use belongsTo for Form and Elements to handle them equally, in a way that:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $form->setName('form');
    $form->setBelongsTo('foo[bar]');
    $elem->setName(null);

    $elem->getNotation();
    // foo[bar][form][]

    $form->setName(null);
    $elem->setBelongsTo('baz');

    $elem->getNotation();
    // foo[bar][][baz][]
    ]]></ac:plain-text-body></ac:macro>

    <p>This would be more "use case centric" as leaving out the name would lead to an Array Notation.</p>

    <p>In my imagination, compared to the suggestion above (which i implemented already and am refactoring and cleaning at the moment),<br />
    the following should happen with an ArrayObject Extension</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $form->foo->bar->item(0)>baz>item(1)
    // maybe this too
    $form->foo->bar->slice(1,4)

    get_class($form->foo);
    // ArrayObject
    get_class($form->foo->bar->item(0));
    // Form
    get_class($form->foo->bar->item(0)>baz>item(0));
    // Element
    ]]></ac:plain-text-body></ac:macro>

    <p>One would do Operations on Forms and Elements in the known way</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $forms = $form->foo->bar->slice(0)
    foreach($forms as $subform) {
    $subform->isValid($data);
    ...
    }
    $form->foo->bar->item(0)->getValues();
    ...
    ]]></ac:plain-text-body></ac:macro>

    <p>Where the attachements will be handled by Form like before, just that the Notary will<br />
    bridge the way from one Form to SubForm and from Form or SubForm to Elements.</p>

    <p>Ahh, forgot to tell about Notary.</p>

    <p>Notary will handle the Structure of the Form and Elements without having references to them.<br />
    The Elements or SubForms which i call Items now, will get An Unique Id in Notary when instantiated,<br />
    which then will be the Key in a Member Array of the Item on which the SubItems get attached.<br />
    So just like the $form->_order['name'] Array at the moment, but with the difference that <br />
    the id is independent of names or other Data.</p>

    <p>That will allow to virtually name and group Items.</p>

    <p>So when instantiating an Element, this Element will then have a member </p>

    <p>$elem->_notary = new Zend_Form_Notary();</p>

    <p>When instantiating Notary this will fetch $notary->_array from Registry which looks like that<br />
    after creating the above Form.</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $notary->_array = array('items' => array('#0' => array()
    '#1' => array('name' => null,
    'path' => 'foo/bar'),
    '#2' => array('name' => null,
    'path' => 'baz'),
    'btree' => array('#0','#1','#2','#2','#1','#0'),
    'index' => array('name' => array('#1' =& $notary->_array['items']['#1']['name'],
    '#2' =& $notary->_array['items']['#2']['name']),
    'path' => array('#1' =& $notary->_array['items']['#1']['path'],
    '#2' =& $notary->_array['items']['#2']['path'])));
    ]]></ac:plain-text-body></ac:macro>
    <p>So now we can do nifty things with $notary like </p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $elem->getNotary()->setProperty('name','foo');
    $form->getNotary()->setProperty('name','fooElem','#2');
    $form->getNotary()->getConcatPathAndName('#2','#0');
    // foo/bar/#/baz/fooElem

    $elem->getNotary()->setProperty('name',null);
    $form->getNotary()->getConcatNotation('#2','#0');
    // foo[bar][][baz][]
    ]]></ac:plain-text-body></ac:macro>

    <p>From Notary we can fetch ChildIdents attached to an Ident or fetching Properties of all Ancestors of an Ident and so on.</p>

  13. Mar 29, 2010

    <p>As i reread the Recommendations, i realized this Notary <a href="http://framework.zend.com/issues/browse/ZF-9516">ZF-9516</a> is able and implemented to handle Metadata <br />
    and to retrieve Idents based on comparison against Metadata Values as well.</p>

    1. Mar 30, 2010

      <p>It is possible as well to implement normalize (for setting), equals, prepare (for retrieving), concat (for Notation) ...<br />
      calling appropriate Properties which are create_function/closures variables.</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $func = create_function('$path', 'return str_replace("[]", "/#/",
      trim(strtr($path,
      array("[" => "/",
      "]" => "")),
      "/"));');
      $elem->getNotary()->setProperty('normalizePath', $func);
      $elem->getNotary()->setProperty('path', 'foo[bar][][baz][]');
      // foo/bar/#/baz/#
      ]]></ac:plain-text-body></ac:macro>
      <p>and even</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $func = create_function('$identProps', 'return $identProps["path"] . "/" . $identProps["name"];');
      $elem->getNotary()->setProperty('concatPathAndName', $func);
      $elem->getNotary()->getConcatProperties(array('path','name'));
      ...
      ]]></ac:plain-text-body></ac:macro>

  14. Aug 13, 2010

    <p>I wasn't able to determine if there will be a default set of markup used when outputting a Zend_Form if not specified otherwise. Currently, that markup looks like:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    <dl>
    <dt><label /></dt>
    <dd><input /></dd>
    ...
    </dl>
    ]]></ac:plain-text-body></ac:macro>

    <p>While this is very semantic from an html and data-layer perspective, it complicates things in the presentation and behavioral layers. I am talking specifically about each field not having a parent node. Having a parent node on a per-field basis dramatically simplifies JavaScript and CSS querying. Might I suggest the below, or a similar variant with a parent node:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    <ul>
    <li>
    <label />
    <input />
    <p class="description" />
    <p class="error" />
    </li>
    ...
    </ul>
    ]]></ac:plain-text-body></ac:macro>

  15. Aug 17, 2010

    <p>Hi,</p>

    <p>Did you planned to automatically bind form's data to an object by using reflection ?</p>

    <p>It would be nice to (optionally) pass to a Form's object an object reference for being populated. In order to do that, objects should have some constraints like well formatted getters and setters. The form fields should have the same names than the object's attributes and the group fields the same name than the nested object attribute and so on.</p>

    <p>That kind of code would be great :</p>

    <ac:macro ac:name="code"><ac:default-parameter>PHP</ac:default-parameter><ac:plain-text-body><![CDATA[
    class Foo
    {
    protected $bar;
    protected $baz;

    public function getBar()

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

    public function setBar($bar)

    Unknown macro: { $this->bar = $bar; return $this; }

    public function getBaz()

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

    public function setBaz($baz)

    Unknown macro: { $this->baz = $baz; return $this; }

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

    <ac:macro ac:name="code"><ac:default-parameter>PHP</ac:default-parameter><ac:plain-text-body><![CDATA[
    $foo = new Foo();
    $form = new FooForm(array(), $foo);
    // filters, sets form data and populate object if it exists.
    $form->setData(array('bar' => 'some value', 'baz' => 'other value')); // or $_POST or other

    $foo = new Foo();
    $foo->setBar('some value');

    $form = new FooForm(array(), $foo);
    $form->getElement('bar')->getValue();
    // some value
    ]]></ac:plain-text-body></ac:macro>

    1. Aug 17, 2010

      <p>I add a precision for non-standard attribute's type, filters should be used (even if i think that the term "filter" is not appropriate).</p>

      <p>Ex. with a Zend_Date attribute :</p>

      <ac:macro ac:name="code"><ac:default-parameter>PHP</ac:default-parameter><ac:plain-text-body><![CDATA[
      class Foo
      {
      /**

      • @var Zend\Date
        */
        protected $date;

      public function setDate(Zend\Date $date)

      Unknown macro: { $this->date = $date; return $this; }

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

      <ac:macro ac:name="code"><ac:default-parameter>PHP</ac:default-parameter><ac:plain-text-body><![CDATA[
      class FooForm extends Form
      {
      public function init()

      Unknown macro: { $date = new ElementText('date'); $date->addFilter(new FilterDate('yyyy-MM-dd')); // converts to Zend_Date object $this->addElements(array( $date ); }

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

      <ac:macro ac:name="code"><ac:default-parameter>PHP</ac:default-parameter><ac:plain-text-body><![CDATA[
      $foo = new Foo();
      $form = new FooForm(array(), $foo);
      $form->setData(array('date' => '2010-08-17'));
      // filters/converts data, and then populates the object
      ]]></ac:plain-text-body></ac:macro>

  16. Aug 20, 2010

    <p>Hi all,</p>

    <p>After spending some time with the current Zend_Form, I will be more than happy to have a replacement. I really like the idea of validator/filter chains being decoupled from Zend_Form. As far as validators/filters are concerned, have you considered adopting an approach similar to <a href="http://docs.symfony-reloaded.org/guides/validator.html">Symfony annotations</a>?</p>

    <p>Usage could be something like this:</p>

    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
    $entity = new EntityObject();
    $validator = new Zend\Validate\ChainGenerator\Annotation($entity)
    $data = array(...) //From request or something

    if($validator->isValid($data)){
    //Do something...
    } else {
    //Do something else...
    }
    ]]></ac:plain-text-body></ac:macro>
    <p>I haven't used Symfony or its annotation reader yet but the one in Doctrine 2 BETA seems to work well though. With annotation readers already available, I imagine it would be trivial to implement. XML, INI (and YAML?) generators could be made available as well. </p>

  17. Oct 11, 2010

    <p>After some reflexion, maybe it would be better to extract binding logic from Zend Form and that ZF 2.0 comes with a databinder component which would be used internally by Zend Form.</p>

    <p>e.g :</p>

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

    namespace Entity;
    use Zend\Date;

    class Foo
    {
    /**

    • @var string
      */
      protected $bar;

    /**

    • @var Date
      */
      protected $date;

    public function setBar($bar)

    Unknown macro: { $this->bar = $bar; return $this; }

    public function setDate(Date $date)

    Unknown macro: { $this->date = $date; return $this; }

    // getters...
    }

    <?php

    $foo = new Foo();
    $form = new FooForm('fooForm');

    // or $form = new FooForm('fooForm', $foo);
    // proxy method for $form->getDataBinder()->setTarget($foo);
    $form->setTarget($foo);

    // proxy method for $form->getDataBinder()>bind($this>getRequest()->getPost());
    $form->bind($this->getRequest()->getPost());

    // convert from string to Zend\Date object before binding the value to the Foo's date property
    $dateConverter = new My\Converter\ZendDateConverter();

    // proxy for $form->getDataBinder()->addPropertyConverter('date', $dateConverter);
    $form->addPropertyConverter('date', $dateConverter);

    // a databinder could be used directly without the need of a Form object
    $dataBinder = new DataBinder($foo);

    // preventing unallowed fields to be mapped, security matter
    // automatically invoked if data binding is used through a form
    $dataBinder->setAllowedFields(array('bar', 'date'));

    // or $dataBinder->addPropertiesConverter(array('dateField1', 'dateField2'), $dateConverter);
    // different method to keep best practices and to not mix parameters data type.
    $dataBinder->addPropertyConverter('date', $dateConverter);
    $dataBinder->bind($this->getRequest()->getPost());
    ]]></ac:plain-text-body></ac:macro>

    <p>A databinder component would be nice and could be used without a form. This way, Zend Form would not be responsible of data binding and delegates that process to an appropriate object, keeping Zend Form focused on forms handling. (i'm really not sure about the good english of this last paragraph <ac:emoticon ac:name="cheeky" />)</p>

    1. Jul 01, 2011

      <p>I have created a similar solution, <a href="https://github.com/szjani/equcms">check the example</a> and the <a href="https://github.com/szjani/equlib/tree/master/tests/Equ/Form">unit tests</a></p>

  18. Aug 16, 2011

    <p>I have some thoughts/concerns regarding the current Zend_Form 1.0 and some of the comments here so far.</p>

    <h4>1.) Decorators / Rendering</h4>
    <p>I'll admit, I am only just grasping the principle behind this pattern, and I can see it has it's advantages. However, you only have to look back a year or so and it seemed that in IRC and on just about every related forum, some developer new to the framework was completely lost as to how he went about changing the damned default DL based output to something a bit more "normal".</p>

    <p>You can argue until you are blue in the face about semantics, but you'll never convince me or a large number of other people that a DL was the most semantic markup for a form.</p>

    <p>As I have already admitted, as I learn more about decorators, I can see their uses. However, as a learning curve, I am going to have to refer to the drupal learning curve used in a recent PHPNW meeting:- <a class="external-link" href="http://28.media.tumblr.com/tumblr_lfojlzGHJ01qdpu1qo1_500.png">http://28.media.tumblr.com/tumblr_lfojlzGHJ01qdpu1qo1_500.png</a></p>

    <p>My thoughts are along the same lines as Benjamin Eberlei, that the rendering of form elements should be done with a partial view script <strong>by default</strong> with decorators being the option for those that need them.</p>

    <p>This is a rough (OK, <strong>very</strong> rough) such script that I have been using for a while now:- <a class="external-link" href="https://gist.github.com/1150056">https://gist.github.com/1150056</a></p>

    <p>Obviously I approve massively of the improvement of passing in just the element and not all it's properties to the view helpers - which would drastically reduce the amount of code in view scripts like mine.</p>

    <p>When it comes to getting the most from my time, I can build 90% of my forms using the view script above and style it a lot quicker than with decorators!</p>

    <h4>2.) Mapping Models directly to Forms</h4>
    <p>Eeeew!! Please just stop now. Do a google search for getters and setters are evil, and then come back.</p>

    <p>I can't think of anything worse for an MVC approach that to bind a form directly to a domain model.</p>

    <h4>3.) Filter/Validator/Decorator chains.</h4>
    <p>I thought we already had Filter and Validator chains, and although I have not looked into PubSub, it sounds like what we should be looking towards is a more generic base "chain" implementation that all of the above can extend from.</p>

    <p>Just my two bits worth, carry on! <ac:emoticon ac:name="smile" /></p>

  19. Sep 05, 2011

    <p>For dynamically-generated or user-configurable forms, it would be very handy if the order values supplied when adding elements or sub-forms did not have to be unique.</p>

  20. Jan 25, 2012

    <p>I see you guys are really into internal stuff (filters, chains, decorators), but not the real use-cases and programmer friendly usage of the module <ac:emoticon ac:name="sad" /></p>

    <p>I'm new to ZendFramework and what makes me really frustrating is the current Zend_Form data handling. </p>
    <ac:macro ac:name="code"><ac:parameter ac:name="title">AlbumController.php</ac:parameter><ac:parameter ac:name="borderStyle">solid</ac:parameter><ac:plain-text-body><![CDATA[
    $request = $this->getRequest();
    if ($request->isPost()) {
    $formData = $request->post()->toArray();
    if ($form->isValid($formData)) {
    ]]></ac:plain-text-body></ac:macro>
    <p>really? Fatal Error <ac:emoticon ac:name="smile" /> Form should be aware of the Request object by itself and extract data from it, so the code looks like:</p>
    <ac:macro ac:name="code"><ac:parameter ac:name="title">AlbumController.php</ac:parameter><ac:parameter ac:name="borderStyle">solid</ac:parameter><ac:plain-text-body><![CDATA[
    if ($form->isSubmitted()) {
    if ($form->isValid()) {
    ]]></ac:plain-text-body></ac:macro>
    <p>To achieve this, the form have to generate 'namespaced' fields, like in Ruby on Rails or other framworks. If the form's init() looks like:</p>
    <ac:macro ac:name="code"><ac:parameter ac:name="title">AlbumForm.php</ac:parameter><ac:parameter ac:name="borderStyle">solid</ac:parameter><ac:plain-text-body><![CDATA[
    $this->setName('album');
    $artist = new Element\Text('artist');
    ]]></ac:plain-text-body></ac:macro>
    <p>then it should generate </p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[<input type="text" name="album[artist]" />]]></ac:plain-text-body></ac:macro>
    <p> not the </p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[<input type="text" name="artist" />]]></ac:plain-text-body></ac:macro>

    <p>Also, the form should generate </p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[<input type="hidden" name="album[submit]" value="1" />]]></ac:plain-text-body></ac:macro>
    <p> automatically, just after the <form>. This way you KNOW the form is submitted or not, so you know if you need to run the validation for this particular form. Currently, you just check if ($request->isPost()) and then have to check if the POST contains an element of your form.</p>

    <p>The current markup is also really hard to use in real world of CSS. The markup I use in my projects:</p>
    <ac:macro ac:name="code"><ac:parameter ac:name="borderStyle">solid</ac:parameter><ac:plain-text-body><![CDATA[
    <form class="zendForm" name="FORM_NAME">
    <fieldset class="FIELDSET_CLASS">
    <legend>FIELDSET CAPTION</legend>

    <div class="field ELEMENT_CLASS invalid required" id="field-FORM_NAME_ELEMENT_NAME">
    <label for="FORM_NAME_ELEMENT_NAME">
    ELEMENT CAPTION
    <span>(required)</span>
    </label>
    <div class="input">
    ELEMENT OR GROUP OF ELEMENTS (like radio buttons)
    </div>
    <p class="hint">ELEMENT HINT</p>
    <p class="error">ERROR MESSAGE</p>
    </div>

    (...)
    </fieldset>
    </form>
    ]]></ac:plain-text-body></ac:macro>

  21. Mar 31, 2012

    <p>I think that realy nice to have feature would be possibility to add Object to Select and Radio elements insted of String.</p>

    <p>What I'm speaking about is something like these.</p>
    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[

    interface \Zend\Form\MultiOptionInterface{
    public function getId();
    public function getLabel(); // maybe __toString ?
    }

    class My\Model\User implements \Zend\Form\MultiOptionInterface{
    public function __construct($login);
    public function getLogin();

    public function getId();
    public function getLabel()
    }

    $selectBox = new \Zend\Form\Element\Select('users');
    $selectBox->addItem(new \My\Model\User('John') );
    $selectBox->addItem(new \My\Model\User('Dave') );
    $selectBox->addItem(new \My\Model\User('Petr') );

    ....

    $selectBox->getValue()->getLogin();
    ]]></ac:plain-text-body></ac:macro>

    <p>It will help a lot to have these posibility now i must convert objects to textvalue and textvalue to Object. If i have more complex form with complex validation i must cuple them with Db/Repository because i need the conversion from / to objects and validation.</p>