Welcome, Guest. Register Now!
   
Mark Forums Read Mark Forums Read Mark Forums Read


Reply
 
LinkBack Thread Tools Display Modes
  #1 (permalink)  
Old 03-17-2008, 11:56 PM
Junior Member
 
Join Date: Mar 2008
Posts: 4
Default Need help with Zend_Form

I'm in the process of learning the Zend Framework.

Here are my issues:

1) Zend_Form generates horrible markup. It does not close input tags properly (uses ">" instead of "/>") and it arbitrarily adds extra markup by putting it in a definition list.

I know that I need to use decorators to fix this, but documentation is kind of vague. How can I fix this?

2) How do I make custom validation errors? I highly doubt ANYONE would use the default error messages...so it should be EASY to define your own custom error messages, right? Does anyone have an example of how this done?

3) How do you validate a field against a database field (e.g. for checking username and password)?

Thanks.

Last edited by action : 03-18-2008 at 03:43 AM.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 03-18-2008, 02:04 AM
kmg kmg is offline
Junior Member
 
Join Date: Mar 2008
Posts: 9
Default

Yes, there are definitely some issues with Zend_Form, and believe me everybody's aware of them. Proposals have already been written up to change some of the functionality. Of specific concern should be the implementation of Zend_Validate validators with Zend_From which do not correspond directly to a standalone implementation of those validators. I'm pretty sure I'm going through all the same things you are right now. Here are some things I've figured out:

1. Here is the code I have been using to create my forms. It's definitely not ideal, and I need to go back and clean some of it up, but it uses decorators to create nice clean html (if you don't count the lack of proper indenting [also, I realize this isn't XHTML, but it is proper HTML, and XHTML is a dead-end anyway]) like so:
HTML Code:
<fieldset id="" action="/login/create/" method="post">
	<legend>Register An Account</legend>
	<form enctype="application/x-www-form-urlencoded" action="/login/create/" method="post">
		<p class="hint">Fields in <strong>bold</strong> are required.</p>

		<input name="token" value="0279aacb27b33548f927857c158f650f" id="token" type="hidden">
		
		<div>
			<label for="first" class="required">First Name</label>
			<input name="first" id="first" value="" type="text">
		</div>
		<div>
			<label for="last" class="required">Last Name</label>
			<input name="last" id="last" value="" type="text"></div>
		</div>
		<div>
			<input name="register" id="register" value="Register" type="submit">
		</div>
	</form>
</fieldset>
I don't recall what the default html output looks like (there was definitely some <dl> stuff going on, which is an interesting approach) but I like mine more. This bit I indented myself for this post of course. It's supposed to resemble this as much as possible: stylephreak demo form

This is the code for the form:
PHP Code:
$form = new Zend_Form('register', array('disableLoadDefaultDecorators' => true));
$form->setAction('/login/create/')
    ->
setMethod('post')
    ->
setLegend('Register An Account')
    ->
setDescription('Fields in <strong>bold</strong> are required.');
    
$form->clearDecorators();
$form->addDecorator('Description', array('escape' => false))
    ->
addDecorator('FormElements')
    ->
addDecorator('Form')
    ->
addDecorator('Fieldset');

$form->addElement('hash''token' /* , array('salt' => md5(time() + '0818fha9dflh023')) */ );


$form->addElement('text''first'
    array(
        
'required'    => true,
        
'label'        => 'First Name',
        
'validators'    => array(
            
'alnum',
            array(
'StringLength'503),
            array(
'regex'false'/^[a-zA-Z]/i')
            ),
        )
    );
$form->addDisplayGroup(array('first'), 'firstGroup');

$form->addElement('text''last'
    array(
        
'required'    => true,
        
'label'        => 'Last Name',
        
'validators'    => array(
            
'alnum',
            array(
'StringLength'503),
            array(
'regex'false'/^[a-zA-Z]/i')
            ),
        )
    );
$form->addDisplayGroup(array('last'), 'lastGroup');

$form->addElement('submit''register'
    array(
        
'required'    => false,
        
'label'        => 'Register',
        
'validators'    => array(
            array(
'regex'false'/Register/')
            ),
        )
    );
$form->addDisplayGroup(array('register'), 'registerGroup');

$form->setElementDecorators(
    array(
        
'ViewHelper',
        
'Errors',
        array(
'Label'),
    )
);

$form->setDisplayGroupDecorators(
    array(
        
'FormElements',
        array(
'HtmlTag''tag' => 'div')
    )
);

$register $form->getElement('register');
$register->clearDecorators();
$register->setDecorators(
    array(
        
'ViewHelper',
        
'Errors',
    )
);

$hash $form->getElement('token');
$hash->clearDecorators();
$hash->setDecorators(
    array(
        
'ViewHelper',
    )
); 
I'm positive there is a more efficient way to handle this, this is just the first method I came across that worked, and I moved onto the next problem.

Passing the disableLoadDefaultDecorators => true into the constructor of the form tells it to not load any decorators (I couldn't ever get the decorators for the errors to change, more about that later). The form parameters are pretty self-explanatory. Keep in mind the order in which decorators resolve. The 'Description' decorator basically takes the description option I passed into the form and wraps p tags around it. I passed the value 'false' for the option 'escape' so that my html tags in the description would remain intact. So first I've got a p tag with some text and html in it. Now I do 'FormElements', so all the decorators use their corresponding viewhelpers to write all the html for all the elements, and that goes right under my p tag. 'Form' is configured so that it will automatically wrap around whatever I've got, so I just throw it in there, and 'Fieldset' is the same way, so it wraps around the Form. 'Fieldset' is cool because it automatically grabs the value of the 'legend' option and creates a legend tag in the correct spot.

I go on to define some fields, and you'll notice I don't decorate them at all here. I was using addDisplayGroup strictly because I wanted to wrap divs around my elements and couldn't figure out another way. =P So then I call $form->setElementDecorators() and pass in some definitions for decorators. This applies those decorators to all of my elements. 'ViewHelper' draws the input tags and their attributes (plus some other stuff depending on the field type and junk), 'Errors' draws the actual list of errors if there are any, and 'Label' draws a proper label tag.

Then I setup my DisplayGroups to write a div around my elements, and move onto the exceptions. I don't want all of my elements to have labels so basically I take them out. This part is totally inefficient, and I'm sure there's some better way to do it that involves setting all the elements I want to be globally changed via $form->setDecorators first and then doing the rest and just changing the 'order' option later, but I didn't want to bother with that.

Anyway, that'll draw you a form. If you reeeeeeaaaaaaally want it to be XHTML you're probably gonna have to go in and do some majoring hammering at the viewhelpers.

2. A bunch of the functionality of validators seems to be lost when using them in conjunction with Zend_Form. This will be fixed at some point, but right now Zend_Form is still pretty new. You're supposed to be able to pass in an option called 'messages' somewhere in the element definition, but I've never been able to get it to work. Supposedly it does work when implementing validators standalone.

In this same vein, stray from the narrow path outlined in the documentation and you've got problems. Some of the validators will lose your parameters, that is, you think they want two, but they actually want three. They stick a mysterious second parameter in there, and I haven't been able to figure out what it does yet (admittedly I haven't gotten around to researching it much yet). Also, when you implement validators outside of Zend_Form, there's this option called 'fields' which basically allows you to pass in other variables to compare stuff against. This doesn't seem to exist when you use Zend_Form, but instead a third parameter is passed into the constructor of every validator of an element attached to a Zend_Form called $context. '$context' is basically just the entire $_POST array, so there you go. For example, here's a class that is just a modified version of one used in the documentation:
PHP Code:
<?php
class Zend_Validate_CompareToField extends Zend_Validate_Abstract
{
    const 
NOT_MATCH 'notMatch';

    protected 
$_messageTemplates = array(
        
self::NOT_MATCH => 'Fields do not match.'
        
);
    
    protected 
$_field;

    public function 
__construct($field null)
    {
        
$this->setField($field);
    }

    public function 
getField()
    {
        return 
$this->_field;
    }

    public function 
setField($field)
    {
        
$this->_field $field;
        return 
$this;
    }

    public function 
isValid($value$context null)
    {
        
$value = (string) $value;
        
$this->_setValue($value);

        if (
is_array($context)) {
            if (isset(
$context[$this->_field])
                && (
$value == $context[$this->_field]))
            {
                return 
true;
            }
        } elseif (
is_string($context) && ($value == $context)) {
            return 
true;
        }

        
$this->_error(self::NOT_MATCH);
        return 
false;
    }
}
?>
All you have to do is pass in the name of a field, and it compares the value of the field it is attached to to the value of the field with the name that you passed in. Just make sure that you pass in that mysterious second parameter, the one that I could likely figure out with a little more doc-scouring:
PHP Code:
$form->addElement('password''confirmPassword'
    array(
        
'required'    => true,
        
'label'        => 'Confirm Password',
        
'validators'    => array(
            array(
'StringLength'206),
            array(
'regex'false'/^[a-z0-9]/i'),
            array(
'CompareToField'false'password')
            )
        )
    ); 
So, in short, defining your own custom error messages to use with validators IS easy, unless you're using them with Zend_Form. If you're using validators with Zend_Form, you might as well just go into the class files and literally rewrite all of the error messages (which really isn't that hard at all).

This answer, I realize, is filled with more questions than answers, and if anybody can show me where I'm wrong, which is likely somewhere, it will serve to help me just as much as it would the OP.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 03-18-2008, 02:05 AM
kmg kmg is offline
Junior Member
 
Join Date: Mar 2008
Posts: 9
Default

3. Write up a validator! As far as I know there isn't a validator that deals with model interaction at all so far, though I'm positive the idea is out there, and there might even be a couple classes put together already. I'm probably going to write one later tonight, because I was trying to figure out this problem yesterday (actually it was checking against a table to see if an email address is unique). The validator will probably take a model instance and a function name is it's parameters, and then pass the value of the field into the member function of the model instance. For your problem, it would have to take an array of values... I submit we should be able to add validators to the form itself! But then that's not really the point I guess.

Hey, sorry this post was so long, a lot of it you probably didn't even want to hear, but I've been meaning to write up some stuff about Zend_Form for a while now.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 03-19-2008, 03:05 PM
Senior Member
 
Join Date: Jan 2008
Location: chicago
Posts: 101
Default

Thank you for shedding some light on the mysterious world of Zend_Form! Also, there was a webinar on Zend_Form a week ago which has yet to be posted on the official site.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #5 (permalink)  
Old 03-29-2008, 07:47 PM
Junior Member
 
Join Date: Mar 2008
Posts: 8
Default

I am upping this great post, i got similar problem. I dont want to mix the Zend Validation classes and mine so i got sub folder My/Validate/Password.php. How could i register the plugin so it can be used. I saw there method addValidator() wich works when you got seperate instance.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #6 (permalink)  
Old 04-01-2008, 03:06 PM
Junior Member
 
Join Date: Mar 2008
Posts: 1
Send a message via AIM to raizyr Send a message via Yahoo to raizyr Send a message via Skype™ to raizyr
Default

for using custom validators I did something like this:

PHP Code:
$password = new Zend_Form_Element_Password('password');
$password->setLabel('Password')
               ->
addValidator(new My_Validate_PasswordConfirmation()); 
The code for My_Validate_PasswordConfirmation is basically the same as kmg's Zend_Validate_CompareToField class above.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #7 (permalink)  
Old 04-07-2008, 04:45 PM
Junior Member
 
Join Date: Apr 2008
Posts: 7
Smile You can do at lot with Definitions List

Not sure what is meant by XHTML is dead, but I think the use of definition Lists for the Form is quite clever you can do so much with them and CSS.

To see an excelent site on the subject take a look at

Max Design - Definition lists - misused or misunderstood?

I have only just started pluging with ZF seriously, I took a quick look with earler versions and thought I doesnt do it but with the View extensions and being able to stack loads of action controllers it does does the stuff.

I still need to go back and studfy this thread I'm sure I can get more out of it.

http://www.zfforums.com/images/smilies/smile.gif

Nic
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #8 (permalink)  
Old 04-18-2008, 05:20 AM
Junior Member
 
Join Date: Apr 2008
Posts: 1
Default

Quote:
Originally Posted by kmg View Post
PHP Code:
$form->addElement('password''confirmPassword'
    array(
        
'required'    => true,
        
'label'        => 'Confirm Password',
        
'validators'    => array(
            array(
'StringLength'206),
            array(
'regex'false'/^[a-z0-9]/i'),
            array(
'CompareToField'false'password')
            )
        )
    ); 
Just to help anyone out who may be getting error messages when trying the above code snippet. Change the:

PHP Code:
array('CompareToField'false'password'
to
PHP Code:
array('CompareToField'false, array('password') ) 
It puzzled me for a bit, the 3rd parameter needs to be an array.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #9 (permalink)  
Old 04-18-2008, 04:17 PM
Junior Member
 
Join Date: Apr 2008
Posts: 2
Default Just an idea

Maybe the answer is that you just have to use doctype helper. Set the doctype before rendering the form.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #10 (permalink)  
Old 05-30-2008, 07:39 AM
Junior Member
 
Join Date: May 2008
Posts: 1
Default second parameter

FYI - that second parameter is for:

If failing a particular validation should prevent later validators from firing, pass boolean true as the second parameter:

Zend Framework: Documentation

cool site guys.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT. The time now is 09:55 PM.