You are not logged in.
Pages: 1
I'm working on a form for a client right now using Zend_Form. I have a constructor that's 100 lines just to render the damn thing! Also the decorator architecture is confusing. Am I the only one that feels this way? Does anyone have experience with other programmatic form-builders?
While Zend_Form has its shortcomings, the built-in validation is a god-send and enables you to easily decouple validation from the form for testing purposes. I've thought of moving the form into config, but that additional layer of indirection seems unnecessarily heavy.
Offline
I really find Zend_Form's rendering to be a pain. Love the validation, hate the decorator architecture for sure. I've pretty much resorted to using decorator scripts (views/scripts/decorators/) to just render the things with my own code. Can be messy, but you can't beat it for getting the stupid things to act the way you want them to. Or, at least, I can't.
$yourForm->setDecorators( array( array('ViewScript', array('viewScript' => 'decorators/yourDecorator.phtml') ) ) );You are not the only one. I have been struggling with it the day it came into existence:P
My previous project, I was so frustrated that I decided not to use it. I manually created the forms in the view and used validation, etc. that came with Zend. It turned out real well and the code is still looks maintainable.
You are not the only one. I have been struggling with it the day it came into existence:P
My previous project, I was so frustrated that I decided not to use it. I manually created the forms in the view and used validation, etc. that came with Zend. It turned out real well and the code is still looks maintainable.
I've heard of people doing that. Works well if you want to Ajaxify the form later. The problem is that you end up essentially writing the view code in two places. I guess there's no silver bullet for this yet.
I'm curious what your view script decorators look like. Care to share an example?
Offline
Yes Zend forms is a pain! I started using it in a project and later changed back to straight up HTML. Forms are not hard to create in html and don't see the benefit in using Zend_forms.
I do use the jquery validation plugin (http://bassistance.de/jquery-plugins/jq … alidation/), which makes client side validation really nice and easy. I don't mind doing the server side validation my self. Easier than trying to learn the Zend_form class imo.
Also the layout of zend_form is hard to set-up
I invested a large amount of time in Zend_Form and whilst I agree that its decorator pattern is confusing at first, it's a useful thing (and design pattern) to have in your ZF toolkit. It's almost certain that you need to delve into custom elements and/or view helpers to render the elements exactly as you require but once you've done this once you'll have that knowledge and it'll be much easier the second time around.
Though I've found this to be by far the hardest and most frustrating area of ZF for beginners, I've really starting to make progress once over this hurdle. A thorough knowledge of Zend_Form helps you understand a lot about the framework's architecture.
Offline
yes zend form sux all ppl around know it.
iam using zend form for validators etc but rendering some .phtml
Offline
Zend Form is actually easy and it's just the decorators that confuse most. This blog posting helped me quite a bit and I refer to it whenever I start a new form.
ive tried using it so many times but just can justify writing that much code which i can rarely get to render as i actually want, i understand the benefits of the validation so it seems i dont get decorators properly, but it just seems too much and the example posted above looked way too long for a 15line peice of HTML markup and validation for 2 input boxes... plus ive never actually worked out how to get other attributes attached to certain elements for example adding a class attribute!
Offline
ive tried using it so many times but just can justify writing that much code which i can rarely get to render as i actually want, i understand the benefits of the validation so it seems i dont get decorators properly, but it just seems too much and the example posted above looked way too long for a 15line peice of HTML markup and validation for 2 input boxes... plus ive never actually worked out how to get other attributes attached to certain elements for example adding a class attribute!
hey Talv,
adding an attribute is pretty straightforward. Here I'm adding a class "swap" to the element:
[code=php]
$fname = new Zend_Form_Element_Text("fname");
$fname->setLabel("Name:")->setValue("First")->setRequired(true)
->setDecorators($this->_standardElementDecorator)->setAttrib('class', 'swap');
[/code]
Regardless, this markup still feels very verbose.
Offline
Glad to see that I'm not the only person that has found it difficult to get their head around form decorators. My current approach is to use view helper scripts to position the individual form elements in the page. Using a form helper then allows me to use the same script if using the form to create/add initial data or to update existing data.
starting in the controller, I will instantiate a form object and assign it to a view variable.
[code=php]
public function addexptAction()
{
$this->view->title = 'Add Experiment';
$form = new Expt_Form_DetailsForm;
$form->setAction( $this->getUrlThisAction() );
$this->view->form = $form; // var_dump($form);die;
[/code]
I set the value of the form action inside the controller, all other form attributes are pretty standard so I set them inside the form class, which I will show later.
An example view script (addexperiment.phtml) might look something like this...
[code=php]
<div class="prepend-8 span-10 append-6 prepend-top content last" id="Title_container">
<h2><?php echo $this->title ?></h2>
</div>
<?php echo $this->ExptDetails01( $this->form ); ?>
[/code]
above you can see that I am passing the form object into the view helper script (ExptDetails01.php)
This next piece of code is the view helper
[[code=php]
<?php
class Expt_View_Helper_ExptDetails01 extends Zend_View_Helper_Abstract
{
/**
* Description: accepts form object of type Expt_Form_DetailsForm and returns form html text
* @param $form
* @return text
*/
public function ExptDetails01( Expt_Form_DetailsForm $form )
{
$content=<<<_HTML_
<!-- START: Form Element -->
<form name="{$form->getAttrib('name')}"
class="{$form->getAttrib('class')}"
id="{$form->getAttrib('id')}"
enctype="{$form->getAttrib('enctype')}"
action="{$form->getAttrib('action')}"
method="{$form->getAttrib('method')}" >
<div class="span-24 maincontent-1 last" id="form_container">
<div class="prepend-1 span-10 last"> {$form->getElement("expt_number")->getLabel()} : {$form->getElement("expt_number")}</div>
</div> <!-- end div: form_container -->
<div class="span-24 maincontent-1 last" id="form_container">
<div class="prepend-1 span-10 last"> {$form->getElement("diet")->getLabel()} : {$form->getElement("diet")}</div>
</div> <!-- end div: form_container -->
_HTML_;
if ($form->getElement("id")) {
$content.=<<<_HTML_
{$form->getElement("id")}
_HTML_;
}
$content.=<<<_HTML_
<div class="span-24 maincontent-1 last" id="form_container">
<div class="prepend-1 span-7 last">{$form->getElement("submit")}</div>
</div> <!-- end div: form_container -->
</form><!-- end form -->
_HTML_;
return $content;
}
} // end class.
[/code]
The allowed form class that is acceptable by this function is restricted to a single type, Expt_Form_DetailsForm, in this example.
If the form is used to insert initial data, the id is a serial which is automatically assigned by the database. If I want to use the same form/view helper as an update form I must pass in an id element which is not in the form class but is something that I add at the controller.
for example in the controller I might have something like ...
[code=php]
// add hidden id element to form so that id number association is kept.
$form->addElement( $id = new Zend_Form_Element_Hidden('id') );
$id->setValue((int)$arrMouse['id']);
[/code]
Now the form class for this example. There are only three elements, a textbox, select box, and a submit button.
[code=php]
<?php
class Expt_Form_DetailsForm extends My_Zend_Form
{
protected $detailsService;
protected $_refTableDiet;
public function __construct( $options = null )
{
parent::__construct($options);
$this->detailsService = new Expt_Service_DetailsService;
$this->_refTableDiet = new Expt_Model_RefTableDietModel; // var_dump($this->_refTableDiet);die;
$this->setName('mouse_form')
->setDescription('This is the Experiment Details Form')
//->setAction() // set in controller-Action
->setAttrib('enctype', 'application/x-www-form-urlencoded')
->setAttrib('method', 'post')
->setAttrib('id', 'expt_details_form')
->setAttrib('class', 'appform');
$formFeName = 'expt_number';
//======================================
$this->addElement( ${$formFeName} = new Zend_Form_Element_Text("$formFeName"));
${$formFeName}->setRequired(true)
->setLabel('Eperiment Number')
//->setValue('')
//->setDescription('Hr.')
->setAttrib( 'size', 15) // size of the form field
->setAttrib( 'maxlength', 255) // size of table field length
->addFilter('StripTags')
->addFilter('StringTrim')
->removeDecorator('label')
->removeDecorator('HtmlTag')
->removeDecorator('DtDdWrapper')
//->removeDecorator('Errors')
->addValidator('NotEmpty', false, array('messages'=>'Please enter the mouse assigned id number.')) // only works when setRequired(true)
//->addValidator('regex', true, array('/^[\d]/', 'messages'=>'Only numeric values allowed.'))
//->addValidator('Between', true ,array(0, 24, 'messages'=>'Hours value must be between 0 and 24.'))
;
$this->set_formElementName( $formFeName );
$this->set_formElementObject( ${$formFeName} );
$this->set_formElementObjectsAssoc( $formFeName, ${$formFeName} );
unset( $formFeName );
//=============================================================================
$formFeName = 'diet';
//=====================================================
$options_{$formFeName} = array( '0' => ' Please Select Diet' );
$options_{$formFeName} = $this->_refTableDiet->getAssocArray('diet_id', 'diet', 'diet_id ASC', $options_{$formFeName} );
$this->addElement( ${$formFeName} = new Zend_Form_Element_Select("$formFeName"));
//$this->addElement( ${$formFeName} = new Zend_Form_Element_MultiCheckbox("$formFeName"));
${$formFeName}->setRequired(true)
->setLabel('Location')
//->setValue('')
//->setDescription('test')
->setMultiOptions($options_{$formFeName})
->setAttrib( 'title', 'location')
->removeDecorator('label')
->removeDecorator('HtmlTag')
->removeDecorator('DtDdWrapper')
//->removeDecorator('Errors')
->addValidator('NotEmpty', false, array('messages'=>'Value is required.')) // only works when setRequired(true)
->addValidator('regex', true, array('/[^0]/', 'messages'=>'Please specify'))
;
$this->set_formElementName( $formFeName );
$this->set_formElementObject( ${$formFeName} );
$this->set_formElementObjectsAssoc( $formFeName, ${$formFeName} );
unset( $formFeName );
//===========================================================
$formFeName = 'submit';
//======================
$this->addElement( ${$formFeName} = new Zend_Form_Element_Submit("$formFeName"));
${$formFeName}->setAttrib('id', 'submitbutton')
->setAttrib( 'style', 'background:#ff9999;color:black;')
->removeDecorator('DtDdWrapper')
;
$this->set_formElementName( $formFeName );
$this->set_formElementObject( ${$formFeName} );
$this->set_formElementObjectsAssoc( $formFeName, ${$formFeName} );
unset( $formFeName );
//=============================================================================
} // end function: __construct
} // end class: Expt_Form_DetailsForm
[/code]
This might look like a lot of needless and time consuming code, but all I have to do is copy and paste from some template code and make a few changes. Sometimes all I may need to do is only assign the name for the code blocks corresponding $formFeName variable.
The key=>values that I use for the select options are pulled from the model using the following function.
[code=php]
public function getAssocArray($keyColumn=null, $valueColumn=null, $where=null, array $arrFirstPairs=null )
{
$arrPairs = array();
if ( ($keyColumn == null) || ($valueColumn == null) ){
// Throw exception, both inputs are required.
}
if ( $where == null ) {
$where = $valueColumn . ' ' . 'ASC';
}
if ( $arrFirstPairs != null ) {
$arrPairs = $arrFirstPairs; //print_r($arrPairs);die;
}
$result = $this->fetchAll(null, $where)->toArray();
// $arrPairs[0] = 'Select Type';
foreach ( $result as $row ) {
$arrPairs[$row[$keyColumn]] = $row[$valueColumn];
}
return $arrPairs;
}
[/code]
You can see that I remove the form decorators for each of the elements, so that associated/imbedded html tags do not interfere with the layout in the view helper.
Hope this has been helpful for someone out there struggling with how to get that form element on your page in just the precise way that you want it displayed. One of these days I'll have to devote some serious study time to understand how decorators work. They must be a good thing; Else, why was it included in the framework.
All the best,
jim
Offline
There is a new Zend Webinar about Zend_Form
Offline
Pages: 1