I've been reading a lot of PHP tutorials lately, and I keep seeing examples of "helper classes", which are mostly used to generate typical HTML components. Forms seems to be popular.
I can accept that this would probably make the code a little clearer, as I am all too familiar with the "klunky-ness" of meshing html with php. Is there any "other" reason? Some kind of performance benefit? I can see why it would be nice if your website was going to have 100 forms in various places, but if you only have one or two it seems like more work than is necessary.
Ease of use and rapid development come to mind. It would actually be slower performance generating HTML with PHP, but I doubt it would ever become the bottleneck of your application (and you could cache most of the HTML output anyway).
For example, which of these looks easier to implement...
<?php
$name = 'abc';
$options = array('a', 'b', 'c');
$selected = 2;
?>
Example 1
<?php echo form::select($name, $options, $selected); ?>
Example 2
<select name="<?php echo $name; ?>">
<?php foreach($options as $value => $node): ?>
<option
value="<?php echo $value; ?>"
<?php echo ($selected === $index) ? ' selected="selected"' : NULL; ?>
>
<?php echo $node; ?>
</option>
<?php endforeach; ?>
</select>
I think you will find the first example much easier to read, less to type and guaranteed to work every time (so long as you coded it correctly).
Also, if your boss says...
Hey zdkroot, we now need to make all password input elements have a red border in IE6.
...you might think to yourself...
I know, I'll use input[type="password"] { ... }. Oh wait, IE6 doesn't support that?
...so you can go into your input generating functions and add a class there which you can reference in your CSS. It will also make changing from /> to > a synch too (if you decide to).
Consider the example you gave - a form builder.
The thing with a form is that you need more than just the HTML. You also need to map those input fields to variables, you need to validate them, you need to save them to a database, you need to pre-populate them with data from the DB.
A good form builder class will handle most of these. If you built the HTML code manually, you'd still be able to modify that easily enough, but you'd have to write your own validation and processing routines.
That's the benefit of using a pre-built class.
There are down-sides as well, of course. Typically, a class like this will make it very easy to create a form that meets the design criteria of the people who created the class. But if your requirements are slightly different to that, it can be quite tricky to force it to do what you want.
Most of the time it does work well, though.
For a selection of reasons why a form helper or library might be helpful you can checkout a question I recently posted A PHP and jQuery form creation and validation library available?
The often give you:
An easy way to validate
Sometimes client side validation is included
Form re-usability
Faster speed of development
Related
I'm a total newbie to CakePHP, but I have a fairly ok grasp on the fundamentals of raw PHP. My problem is getting over the hump and learning how to conform to the CakePHP framework. I've read up on Cake and have done the examples, but the only way I'm going to learn this is to jump in head first and start coding something on my own. My question is, how do I convert something this simple into cake. IE what goes where, Controller/Model/View.
<?php
if (isset($_POST['guess'])) {
//my php
};
?>
<form name="form" method="post" action="#">
Your guess: <input type="text" name="guess">
<input type="submit" value="Submit">
</form>
All I want to do here is pass a number from user input to php (no database connection), run some php calculations, then return the results to the view. Do I have to use the form helper? It seems to center around database queries... And what goes where? From my angle, it seems cake may complicate such a simple snippet.
Much appreciated if someone could make some connections/relations to what I'm use to, and get me rolling.
I recommend to read CakePHP´s Blog Tutorial.
At first, create a view located in app/View/Guess/create.ctp:
// Using Form-Helper
<?php echo $this->Form->create(); ?>
<?php echo $this->Form->input('guess'); ?>
<?php echo $this->Form->end('Submit'); ?>
At second, create a controller located in app/Controller/GuessController.php:
class GuessController extends AppController
{
// stop using a model
public $uses = array();
function create()
{
if($this->request->is('post', 'put'))
{
// now do something with your form data
$doSomething = $this->request->data['Guess']['guess'];
}
}
}
That´s it.
Now you should call your action via url http://examplehost.com/Guess/create
At the beginning, CakePHP seems to be complicated, but it isn´t. I think, it is important to understand the MVC. That makes it easier to learn all common PHP-Frameworks.
At a first glance, a simple form like above might be implemented easier via pure php and html code. But if you want to do deeper tasks (e.g. validation, authentication, autorisation, security ...) and want to have a clean code, you will recognize the advantages of that framework.
Like this:
<script>
setSomeStuffUp();
<?php if ($otherStuffNeedsToBeDone === true) { ?>
doSomeOtherStuff();
<?php } ?>
breakSomeStuffDown();
</script>
Came across something like this at work- done with templating (Smarty), so it looks a bit cleaner- but not by much! Also echoes some template variables used for things such as jQuery selectors, and other little unpleasant-looking bits.
What's the proper way to do this? Load the data that needs to be used for logic in the JS as JSON via AJAX? HTML data attributes?
Something about it just smells bad, bad, bad.
Thanks everyone.
It is bad practice to use language X to generate code in language Y.
Try "decoupling" the two languages, for example, like this:
<script type="text/javascript">
var data = {
id: "<?php echo $id ?>",
...
};
$(document).ready(function(){
$("#" + data.id).on("click", function(){
/*do something*/
});
});
</script>
This way, PHP only cares about populating the data structure and JavaScript only cares about consuming the data structure.
Echoing configuration variables and some javascript initialization code from server doesn't sound too bad in general, but if such js-injection-from-server pieces are all over the place then you're right, it's ugly, at least because such code is difficult to manage.
Just try to centralize any kinds of initialization and do the rest in statically-defined client-side JavaScript logic.
UPD. #Oscar Jara is talking about the same thing and provided a good illustration. But often even such cases can be avoided if server-side logic provides data for JavaScript processing via HTML (after all, that's what HTML is for).
Here's a trivial example that you can often encounter. Say you want to output a gallery that will be enhanced into a carousel via JavaScript.
Server generated HTML:
<ul id="myGallery">
<li><img src="img1.jpg /></li>
<li><img src="img2.jpg /></li>
<li><img src="img3.jpg /></li>
...
</ul>
And then you have your static JavaScript code initialize the carousel when DOM is ready:
// when DOM ready...
AwesomeCarousel.init($('#myGallery'));
Here the data prepared by the server is this piece of HTML with a list of images, no need to generate JavaScript explicitly loading every image. You can pass arbitrary data via the data-* attributes.
Personally, I use PHP in JS in many instances. Sometimes it is to populate a variable with JSON data, a page id, or something of that nature. As far as I am concerned, PHP is designed to write the code that appears on the page, and JS is designed to interact with the user once the content is there.
I do get what you are saying, in that there are probably cleaner ways of doing this. You mentioned AJAX, which would probably be cleaner and would definitely help the flow of the document being output. The only issue is that you have to make a second request to the server for some very simple and meanial variable. A few milliseconds isn't huge, but in the a production website, you probably don't want to be making that additional request and bogging down server resources.
In response to what the cleanest way to do it would be, if it was that big of a deal... I would create a separate JS file with that code and then use the server to include that individual file if needed. Again, I don't do this, but I think it would look the cleanest in the template.
If you want to get really out-there, you can have the HTML page request a .js file, coupled with their session-id or some other indicator of who they are, operate the .js call as a PHP call, dynamically build the JS based on what their session requires and then output it back to the browser as a .js filetype.
But that's a lot of work.
If you'd like something that smells less, have PHP dump either a JSON-string at the end of your file:
var cfg_string = "{\"username\":\"Norguard\", \"new_messages\":[......]}"; // client
$cfg_obj = array(); // whole lot o'PHP
$json_encoded_cfg = json_encode($cfg_obj);
echo "var cfg_string = {$json_encoded_cfg};" //server-side
And then parse it, in the client for added safety...
...or just outright create a map in the template:
$cfg_string = "var dataMap = {";
foreach ($cfg_obj as $key => $val) {
// print key:val all pretty-like,
// handle commas (ie: no trailing comma at the end), indent with tabs or spaces
// if you want, count the number of items so that the object closes ({})
// without any newline operator, if there are no config settings
}
echo $cfg_string;
Both of these are clean and unobtrusive and keep everything separate.
The config data/text can go right above whatever your init/loading code is going to be, and be passed in as a parameter to that init-logic.
If all you're doing is passing data from the server-side language to the JavaScript code, then that's fine. Plenty of CMS packages out there do it.
I don't really see the need to conditionally generate JavaScript code on the server side. Maybe there's a use case for it but JavaScript is a language itself, so why not just put the logic in the JavaScript code?
So let's say i have a form where the user can add as many dogs as they want by pressing a + button.
The form is like:
Dog #1 <br/>
<input name="house[dogs][][name]" value="<?=set_value('house[dogs][0][name'])?>"/>
<input name="house[dogs][][age]" value="<?=set_value('house[dogs][0][age]')?>" />
Dog #2 <br/>
<input name="house[dogs][][name]" value="<?=set_value('house[dogs][1][name'])?>"/>
<input name="house[dogs][][age]" value="<?=set_value('house[dogs][1][age]')?>" />
On CodeIgniter, I run a form validation in order for set_value() to work as well:
$house = $this->input->post('house');
$dogs = $house['dogs'];
$i = 0;
foreach($dogs AS $dog){
$this->form_validation->set_rules("house[dogs][$i][name]", 'Dog Name', 'required');
$this->form_validation->set_rules("house[dogs][$i][age]" , 'Dog Age' , 'required');
$i++;
}
This whole thing doesn't work, How to make set_value() support array inputs like that?
Thanks in advance.
You might have to make the input name the exact same as the first parameter of set_value().
One might not be able to be [], while the other can use [0].
Very related: http://codeigniter.com/forums/viewthread/179581/ Ironically, a post I made months ago that was bumped this morning.
Also related: CodeIgniter: Validate form with multidimensional POST data
<ignore>
To make a long story short, Codeigniter does not handle indexed field names very well by default.
To simply repopulate the input and work around set_value()'s shortcomings, you can try something like this:
<?php
$value = isset($_POST['house']['dogs'][1]['age']) ? // was the value posted?
form_prep($_POST['house']['dogs'][1]['age']) : // if so, clean it
''; // if not, leave empty
?>
<input name="house[dogs][1][age]" value="<?php echo $value; ?>" />
Since you're probably using a loop to output these, I don't think it will be too much of a bother. You could populate a separate array of values and read those instead if you wish, you get the idea. set_value() automatically runs form_prep(), so that's why I added it.
I'm not too sure about the validation. You may have to do the validation yourself, which while bothersome, shouldn't be too difficult. Remember you can always run the validation methods manually. Example:
if ($this->form_validation->valid_email($this->input->post('email')) {}
You may want to just take the easy way out and change your field names to use a single index, like dog_age[], which I believe will make the validation easier for CI to handle. Best of luck, hoping for a fix one of these days in CI core.
</ignore>
EDIT: I have no idea how this escaped me, but apparently validation and set_value should in fact work as expected - not sure if this was a recent change or if the issue never really existed. I definitely remember having issues with it before, and the linked posts suggests others are too. Check out this answer though:
CodeIgniter: Validate form with multidimensional POST data
I tested it (running 2.0.2) and it does in fact work. I don't see anything in the change log, but I did test it and it did work. Make sure your on the latest version and try again perhaps, or let us know if I'm missing something here.
Like your other answer says, you probably just have to explicitly index the field names like name="house[dogs][1][name]" instead of name="house[dogs][][name]".
I'm creating a FORM with PHP for an intranet webpage. Another PHP script is called by submitting the form.
Before anyone asks, the form does not allow any uploads, and although the values entered in the form find their way into an SQL query, I strip out everything but numbers.
I'm wondering if there would be a advantage in using the same PHP file for both the FORM and the ACTION?
Obviously, increased complexity is the penalty — ie, figuring out, when invoked, if the FORM is to be created, or if the SUBMIT button has been clicked — but what would be the benefits?
EDIT: Note, the PHP in 'submit' mode does not redisplay the form, it does something entirely different. This is the source of the complexity I was worried about.
The form is used to enter values which are checked against values in a DB, but there are no changes made to the DB.
I tend to find it more maintainable to have the php that creates the form separate from the php that is called by the form.
It will also reduce (though it isn't noticeable) one if statement to determine if this is a form request or filling in the form.
But, the problem is that unless you are going to take them to a new page, you will have to get the values back into the form which can be more complicated.
So, if you want to keep the values in the form, even after the form is processed, then leave the form processing logic at the beginning of the file, otherwise I would opt for maintainability and have them in two files.
In most case, I prefer that.
Keeping both together make the code more 'cohesive' as the code of accepting value (via form) is in the same php file (called it View and Control). To me this is an advantage.
However, the code that manipulate database should be separated in other file as it not the same as accepting value (called it a model library). This make it less-coupling as accepting and manipulation is separated. This decoupling will reduce the complexity you are worrying about.
Another advantage of is the URL. The users will see it as from the same page.
However, this is totally depends on your overall system metaphor and work flow. For example, it make better sense to the users that addBook.php handle book adding form and show that the adding has success or fail. Comparing that too having two addBook.php, addBookProcess.php.
What I am trying to say is that the flow of pages should be a more important factor to determine if you want to separate or combine them. Decoupling interface/logic code will helps you reduce the complexity if pages need to be combine into one php file.
Just my though.
Form is about user interface, action is about doing something with data.
The part of code that actually processes user input must certainly be separate from the form structure.
The form code must accept default values (or values previously entered and found to be invalid), error messages etc. It must have nothing to do with usage of successfully submitted form data.
If you allow user to change invalidated input, then you must have action URL the same as form.
If successful submission leads to something unrelated, then its URL must be different from that of the form. Basically, you must redirect user from the URL where the form got accepted to the next URL.
If you're doing AJAX, none of this applies.
It depends!
The upside to having them in one file is that it puts a single block of functionality into one place and allows you to handle form validation. The downside is increased complexity. It really starts to suck if you have the markup for both pages in one file.
I would suggest having 3 files - the main PHP handler, the template for the form and the template for the result page. The main PHP file would look something like this:
<?php
$error_message = "";
if ($form_submitted){
if ($form_validated){
include("inc-result.txt");
exit;
}else{
$error_message = "something went wrong!";
}
}
include("inc-form.txt");
?>
if validation fails, the logic drops you back to the form, where you can display the previously entered values, along with the relevant error message.
it does depend but in the long-term I would suggest separation of forms and business logic.
For quick projects I do understand the short-term gain of keeping it in the same page but you never know when the form you did needs to be added with features or needs to be turned to an ajax form. If you keep your logic separate from the form you would be ready for these changes quicker.
Well, mainly if you want to re-show the form to the users without losing data, then you can just write something like this:
<input type="text" name="myInput" value="<?php
echo htmlspecialchars(isset($_POST["myInput"]) ? $_POST["myInput"] : "");
?>">
Update: here is an example of this method:
<?php
$error = "";
$result = "";
$a = isset($_POST["a"]) ? $_POST["a"] : "";
$b = isset($_POST["b"]) ? $_POST["b"] : "";
if ($a !== "" && $b !== ""){
if (is_numeric($a) && is_numeric($b))
$result = sprintf("%s + %s = %s", $a, $b, $a + $b);
else
$error = "You must enter two numbers!";
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head><title>Sum numbers</title></head>
<body><form method="post" action="<?php print htmlentities($_SERVER["REQUEST_URI"]); ?>">
<p><strong>Enter two numbers to add them together.</strong></p>
<?php if ($error){ printf ("<p><em>%s</em></p>", htmlspecialchars($error)); } ?>
<p>
<input type="text" name="a" value="<?php print htmlspecialchars($a); ?>">
+
<input type="text" name="b" value="<?php print htmlspecialchars($b); ?>">
<input type="submit">
</p>
<?php if ($result){ printf("<p><strong>%s</strong></p>", htmlspecialchars($result)); } ?>
</form></body>
</html>
It seems like you should do 2 things:
1) create controller that steps in to see if you are doing an edit action or a display action
you already have the start of one at the top of your file there, just make it include "form.php" (your form) after it does it's business. So yes, make 2 files.
2) pull all that crappy formatting code up into the controller. Calculate all your values before the form is ever loaded. This includes running htmlspecialchars on all your form elements that need it. You can even loop through them to save lines of code:
i.e.
$cleanTheseVars = array ($a, $b, $c $error, $result);
array_walk($cleanTheseVars, 'htmlspecialchars' );
I've read the manual many times, I've scoured the posts offered by Google on the subject, I have even bought a couple of books that deal with ZF. Now, why am I still confused?
I can, using Zend_Form, make a form that validates and functions fine. What I cannot do it make a form that looks exactly like I want it to look with the error messages that I want it to have. I want custom buttons, I want funky layouts, I want to insert text in the midst of the form, etc.
Does anyone have a simple way of achieving these sorts of things? Something that makes me feel like the framework is saving me time rather than costing? I could forego Zend Form... make my own form, have its action hit a page to validate and process the posted data and I could do it about as fast as I can type but I really want to "get" this and be able to use it as it was apparently intended.
Any advice? Any simple "how to's" for custom buttons, funky layouts and basic (or rather advanced as there are tons of basic tutorials that skip over the harder issues) "getting things done" with zend form?
Barrett Conrad's advice is what I would have suggested. Also, keep in mind that you don't need to use a form object to render your form.
One thing you could do is create a form in your view script that has elements with the same name as a form class.
Your HTML form:
<form action="/login/" method="post">
<fieldset>
<label for="username">Username:</label>
<input type="text" size="10" name="username" />
<label for="password">Password:</label>
<input type="password" size="10" name="password" />
<input type="submit" />
</fieldset>
</form>
Your class:
class LoginForm extends Zend_Form
{
public function init()
{
$username = $this->createElement('text','username');
$username->setRequired(true);
$this->addElement($username);
$password = $this->createElement('password','password');
$password->setRequired(true);
$this->addElement($password);
}
}
Your form class reflects your HTML form, each element in your class has its own validators and requirements. Back in your action you can create an instance of your form class and validate your post/get vars against that form:
$form = new LoginForm();
if ($this->_request->isPost()) {
if ($form->isValid($this->_request->getParams())) {
// do whatever you need to do
} else {
$this->view->errors = $form->getMessages();
}
}
You can display the the error messages at the top of your form in one group, using this method.
This is a basic example, but it allows you to have total control over the presentation of your form without spending the time to learn to use decorators. Much of the strength of Zend_Form is in its validation and filtering properties, in my opinion. This gives you that strength. The main draw back to a solution like this is that your view script HTML form can become out-of-sync with your form class.
Render each element individually in your view - for example
<!-- view script here -->
<form method="POST">
Name: <?php echo $this->myForm->getElement('name')->render(); ?>
some other text between the fields
Birthdate: <?php echo $this->myForm->getElement('birthdate')->render(); ?>
<input type="submit" />
</form>
This maintains the ability to use the Zend_Form view helpers (i.e. to display error messages and maintain the values of the form fields when validation fails) but gives you full customization ability.
If you want to go further, then turn off the default decorators of the individual form elements and then either attach your own to further customize exactly what tags are used (i.e. for error messages and labels) or don't use decorators at all (other than to render the form element itself) and then write all the surrounding HTML manually. Complete customization ability without losing the benefits of Zend_Form, both at the form level and at the view level.
Matthew Weier O'Phinney has started a series of blog posts about Zend_Form decorators:
The simplest Zend_Form decorator
From the inside out: How to layer decorators
Rendering Zend_Form decorators individually
Creating composite elements
Currently we've got the new and shiny Zend\Form which is even more complex than the old component but also much more controllable, encapsulated and powerfull. So, what I said below doesn't apply. The new component is IMHO a huge improvement because it...
...gives you full control over how you want to render your form, you need to write a bit more view code but it's worth it
...separates data, logics and view to the maximally possible extent
...makes use of the HTML5 form elements
...gives you many options how you want to put your forms together, e.g. hydration, annotations, etc.
Old answer regarding Zend_Form
I can not really help probably because I have exactly the same problem. I think the Zend_Form decorators are powerful but by far the least programmer friendly and non-intuitive piece of ZF I've seen so far and I've used a major part of the ZF in various projects.
That said I can only give a few hints from my experience:
filters are easy to use without using form
most if not all of the things you want to achieve are done with the help of decorators
I started with small forms and added stuff piece by piece but I don't get some of the stuff I'm doing in some of my forms because the result is based on trial and error (mainly with the decorators)
I've got information from the zend mailinglist which I couldn't have found anywhere on the web
From the related questions to this on the right hand side it is obvious that there is a lack of comprehensive documentation for Zend_Form especially given it's non-intuitive nature. I would really like to see the ZF guys do something about this as much as I like Zend Framework.
So this answer is probably just to let you know that you're not the only one having the this problem.
or alternatively you could use jedi mind tricks of course!
To add to what was said:
Dont be afraid of the decorators, you'll be using them lots if you decide to stick with Zend_Form. It's fairly straightforward once you 'get it', unfortunately the docs are weak and playing with it is almost the only way to get there.
The ViewScript and ViewHelper decorators give you lots of power.
Don't be afraid to dig through the source for the different decorators that exist and see how they're doing things (I gained a fair amount of insight comparing the original decorators with the dojo ones).
I think what Sean was suggesting is that you don't need to call form->render, you can use something like this in your viewscript.
<someHtmlThingy name="blah" value="<?php echo $this->formInstance->getElement('whatever')->getValue(); ?>" />
I worked on one project (pre Zend_Form) where we built sets of validators and used standard viewscripts all the way through. It was a little more work (plumbing for error messages and the like), but not excessive compared to creating elements with Zend_Form.
If you just want to add arbitrary markup before or after your form elements without using the ViewScript decorator, you could use my AnyMarkup decorator: http://www.zfsnippets.com/snippets/view/id/62
For example, here is how you would prepend an input field with an image inside a wrapper tag (needs include paths for autoloading to be set correctly):
$form->addElement('text', 'my_field', array(
'label' => 'Enter Info:',
'decorators' => array(
'ViewHelper',
array('AnyMarkup', array(
'markup' => '<span class="imgwrapper">'.
'<img src="info.png" alt="info icon"/></span>'),
'placement' => 'prepend'
),
'HtmlTag',
'Label'
)
);
Skipping out on the form-wide decorators (IE - printing individual elements of the form rather than just relying on the Form's standard View Helper to handle everything) is one way to get a bunch of control back.
Another option is to simply hand-code your form and only use ZF to handle validation and filtering.
Unfortunately, the more complex issues are skipped over because without a real specific purpose or goal in mind, it's really hard to write an example or how-to. I spent some time helping out another developer here on SO who wanted to modify the way hidden elements were displayed, but his case was very specific so it was easier to drill down into specifics.
The majority of the more complex tasks really come down to extending the default helper for a specific field type. For example, I had a project where I wanted to apply the class "error" to all fields that did not pass validation after a form had been submitted instead of writing out the validation error text:
<label for="field">Label:</label>
<input type="text" name="field" id="field" class="error">
It was a fairly complex process because the actual form element is not available to the view helper by default, so the helper cannot check if the element has a validation error. So I went about the following process:
I had to create a customer view helper for each field type that I wanted to apply the "error" class to. In it, I overrode the formXXX() method, and add a check to see if the element had an error. Additionally, I added a setElement() method that the decorator could call to set an instance of the element so my helper could check for errors.
Next I had to override the default Zend_Form_Decorator_ViewHelper. In it, I accessed the view and instantiated the helper for the form element type and checked for the existence of the setElement() method I created in my view helper, setting it if it existed. By doing this, I could extend some form element types and not others without busting the entire script.
In my init() function for each form, I had to add a new element prefix path (addElementPrefixPath('My_Form_Decorator'), 'path/to/decorator')) which pointed to my new form decorator.
Finally, I had to add the helper path to my application so that Zend Framework could find the helpers I had created in the first bullet point: addHelperPath('/path/to/helpers', 'My_View_Helper');
You can see why writing complex tutorials really requires real world problems. The great part about setting up these kinds of helpers, or complex decorator schemes is that, all be it annoying up front, it allows you to very easily create many forms that adhere to the same design scheme and modify their output uniformly very quickly if changes need to be made. But if on the other hand you feel like you're spending a great deal of time figuring out how to do what should be a simple task for the benefit of one form, I would say skip it!
If you would like help for something more specific, however, I would be more than happy to help. Just pose another question (or update this one) and I'll do my best to help out.
whycantitbemorethan25c mentioned them above, but ViewScripts give you extremely fine-grained control for rendering forms. Zend_Form is meant to be fast and so it assumes many defaults like standard decorators and orders the element the way they were added to the form object. With the ViewScript you can skip much of that that and place all of your elements however you would like within normal HTML.
Don't skip over the concept of Decorators entirely though. They style the individual elements even if they are used in a ViewScript later. For example, you can use them for error messages as others have suggested.
If you have very complicated form that has multiple data points with similar actions (think of a list of users with active/inactive buttons and a delete button for each) you should consider Zend_Form_SubForm. The subforms can utilize the ViewScripts just like normal forms and if you cascade a form with a ViewScript with subforms with their own ViewScripts you end up with nicely contained logic and presentation that is much more powerful than just a straight form.
I wrote some sub-classes to Zend_Form and the decorators to make it layout the form in a <table>. It even had some special tricks to do things like make multiple submit buttons show on the same row.
Took a full day of hacking around to get it working. It was written against Zend 1.5.1 so don't know if it will work with the current version, but if you are interested I could probably upload the source somewhere.
This seems to be a very common complaint with Zend Forms.
(I know I'll get poo-poo'd by the CSS purists over using tables to layout forms, and while I agree that CSS is better for most things, I have yet to see good form layout using CSS that doesn't look like a butt-ugly kludge. With tables the forms 'just work' pretty much on every browser I need them to.)
EDIT: Okay, speaking of butt-ugly kludges, I've put my code for producing tabular zend forms in github. Go here to see it. (Because gaoshan88 asked for it.)
ANSWER HERE. HOPE it will help you. I went through the enormal amount of information till I found it.
<table>
<tr>
<td>Page name: *</td>
<td><?php echo $this->pageForm->header_title;?></td>
</tr>
<tr>
<td>H1 tag: *</td>
<td><?php echo $this->pageForm->h1_tag;?></td>
</tr>
<tr>
<td>Page URL: *</td>
<td><?php echo $this->pageForm->url;?></td>
</tr>
<tr>
<td>Meta Description: </td>
<td><?php echo $this->pageForm->meta_description;?></td>
</tr>
<tr>
<td>Meta Keywords: </td>
<td><?php echo $this->pageForm->meta_keywords;?></td>
</tr>
<tr>
<td>Short Description: *</td>
<td><?php echo $this->pageForm->short_description;?></td>
</tr>
<tr>
<td colspan="2"><a href="<?php echo $this->websiteUrl;?>backend_template/list?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=200&width=300&modal=true"
title="add a caption to title attribute / or leave blank" class="thickbox">Open iFrame Modal</a></td>
<td>
<a href="<?php echo $this->websiteUrl;?>backend_template/list?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=200&width=300&modal=true" onclick="javascript:getDataFromAddPage()" title="Select Template For Page" class="thickbox" > TEST FORM </a>
</td>
</tr>
<tr>
<td>Featured: </td>
<td><?php echo $this->pageForm->featured;?></td>
</tr>
<tr>
<td>Mark as 404: </td>
<td><?php echo $this->pageForm->is_404page;?></td>
</tr>
<tr>
<td>Show in Navigation Menu: </td>
<td><?php echo $this->pageForm->in_navmain;?></td>
</tr>
<tr>
<td>Show in Static Menu:</td>
<td><?php echo $this->pageForm->in_navstatic;?></td>
</tr>
<tr>
<td><?php echo $this->pageForm->submit;?></td>
<td><?php echo $this->pageForm->button_close;?></td>
</tr>
</table>
You probably have solved this by now, but I've been doing some work and needed a similar solution.
form->getSubform('subform');
foreach ($subform as $key => $value) {
//some markup and custom code here
print $value;
//some markup and custom code here
}
?>
within the foreach loop, you can add table markup. If you've named your keys for your table rows appropriately, they should match up with the form keys. You could even use a loop that grabs the appropriate subform by key, or even an element by a key. you could skip the foreach loop if you know the keys, and simply say print $subform['somekey']; assuming you set the main form by saying $form->setIsArray(true); (not sure if that last part is strictly necessary, but for complicated forms, it should be set like that anyway.
I removed the default decorators so I could have complete control of printing within each element. Zend_Form ought to have a built-in method for grabbing individual elements a little more easily.. but I think this works pretty well.
Hope that's helpful to someone!
Sean McSomething's first advice is the way to go for me. I've always thought that doing <?php echo $this->form ?> to render a form is too magical. I'll take it a step further though and render individual decorators rather than individual elements via $element->renderDecorator() magic methods. This way, you won't have to worry about the order in which you defined your decorators. You just need them to be there, and you won't have to add those pesky, unintuitive HtmlTag decorators. I made a blog post about this.
I'm not sure if Zend already has that feature but, a quick solution would be to extend the class , make it accept a html template.
For example:
<?php
$form = new zend_form_whatever($field_list + $validators + $template);
echo $form;
?>
template:
<form id="my_custom_form">
<label>{label.email}</label>
{input.email}
<span class="red">{error.email}</span>
<div>
{label.password}
{error.password}
{input.password}
</div>
<div class="purple">{input.submit}<div>
</form>