Brief Summary
This question is asking for guidance on how to deal with Zend Form
library that allows me to specify how to construct each form element (Controller side) and how to render each element (View side), essentially creating 2x amount of work, when compared to a non-Zend-Form approach where each form element is dealt with exactly once -- in the View only
How Zend Form does things
On my Controller side I can use Zend Form to build up each form element. Note: in the code I want to show that I can build Object Oriented HTML elements and populate their values and even attributes (including CSS attributes I want to render later) all inside the Controller code programmatically.
Exhibit A - Zend Form Controller Side
//create checkbox
$checkbox = new Element\Checkbox('construction');
$checkbox->setLabel("Construction: ");
$checkbox->setChecked(true);
$checkbox->setAttribute('onclick', 'return false'); // disable checkbox
// Set up
$listPrice = new Element\Text('listprice');
$listPrice->setLabel("List Price: ");
$listPrice->setValue('123.00');
$listPrice->setAttribute('disabled', 'disabled');
$listPrice->setAttribute('style', 'color:black;text-align:right');
$listPrice->setAttribute('size', 9);
// Assemble Form
$form = new Form('form');
$form->add($checkbox);
$form->add($listPrice);
// return rendered HTML
return $this->partial("form.phtml", array(
'form' => $form
));
Then in my View
I want to show first that in View, ZF2 sometimes takes up the bulk of actual HTML form rendering and I don't have to do much sometimes. i.e. I could just use $this->form()->render($form)
to render out entire form for me, but then I would not be able to place custom style on each element if I so desire. And also all the elements will be rendered in a single row, which is rarely what I want.
In my case in the next code block below I had to go deeper and semi-automate form rendering, to be able to add my own HTML elements such as <p></p>
during the rendering process. i.e. I had to use things like openTag
and closeTag
and formRow
methods.
Exhibit B - Zend Form View Side
/**
* inside view template - with custom HTML
* custom HTML is one that contains form_row class
* It will not render if I use $this->form()->form($form)
* to render out complete form in one go.
*
* @var $this \Zend\View\Renderer\PhpRenderer
* @var $form \Zend\Form\Form
*/
$form = $this->form;
?>
<style>
.form_row {
margin-bottom: 14px;
margin-top: 14px
}
</style>
<fieldset>
<?php
//renders <form ... >
echo $this->form()->openTag($form);
//loops through each form element, and passes it to "formrow" method
//that renders out full element in HTML
foreach ($form as $element)
$formContent .= '<p class="form_row">' . $this->formrow($element) . '</p>';
echo $formContent;
//renders </form>
echo $this->form()->closeTag();
?>
</fieldset>
But, the deeper I go, the more code I have to write. If I was desiring to custom-style each element, I would have to manually refer to each element in my View
Rendering Individual Element with custom styling using Zend Form
<label>
<span><?=$this->formLabel($form->get('listPrice'));?></span>
<?=$this->formInput($form->get('listPrice'));=>
<?=$this->formElementErrors($form->get('listPrice'));?>
<div id="custom_form_div_between_elements">
Custom div that would not be rendered inside this form,
if I left ZF2 on auto-pilot like in a previous example
</div>
</label>
Imagine doing the above for each Form Element.
So essentially I write code, both programmatically defining form elements in Controller and then write code to render them out in the view. Double Work. Double Code.
Question
It Bothers me that I more often than not write code twice in a way (for both Controller and View) to deal with each form element.
I could instead do better by placing everything into my view script like i.e.
Exhibit C - Example not using Zend Form
(rendering my own element)
<label>
<span>List Price: </span>
<input name="listprice" disabled="disabled"
style="color:black;text-align:right" size="9"
value="<?=$price?>" type="text">
</label>
Exhibit D - Full 'real code' [select] example when not using Zend Form
<select name="id" id="modelid" class="validate[required]">
<option>blank</option>
<?
$sql = "SELECT distinct(model), id FROM product GROUP BY model";
$result = db_query($sql);
for ($i = 0; $i < db_num_rows($result); $i ++)
{
$row = db_fetch_array($result);
?>
<option value="<?=$row['id']?>"
<?=$productid == $row['id'] ? ' selected="selected"' : ''?>>
<?=$row['model']?>
</option>
<?
}
?>
</select>
Question Summary
ZF2 lets me use Zend Form
code to create Form Elements in Controller, populate them with values, and then use various Zend facilities to render the elements in the View. Depending on how detailed you want to get (i.e. if you want custom styling for each element), you are doing quite a bit of work for each element, which feels like it is duplicated -- you have to deal with each element in your Controller and in your View. Granted, some work is easier, i.e. in a <select>
or <input type="radio">
element you don't have to deal with hacking up PHP and HTML to make sure a select box displays with a particular value as selected. Zend takes care of that for you.
Now it's great if you just use native default Zend Form facilities to output whatever it gives you. You then do work only in Controller. But the moment you want custom styling, you do additional work in View, sometimes pretty much having code just as much code for each element of the form in the View as you have in Controller.
Bonus Questions
What problem does Zend Form solve by splitting Controller & View code? Am I using this correctly? (Is this 2x work justified?)
Will I do better do something like move all the Zend Form code Controller into and have the all the "2x code" live in the View?