2009年4月20日星期一

RE: [fw-mvc] Form filters not working

After sending the email, I looked through the code and played with it a bit and came to the same conclusion. I also figured out the answer to my other question (that wasn't explicitly asked). For those who are interested, here is my revised code which has a number of changes.


>     $form = new MyForm();
>     $form->submit->setLabel('Save');
>     $this->view->form = $form;
>     if ($this->_request->isPost()) {
>         $formData = $this->_request->getPost();
>         if ($form->isValid($formData)) {
>             $model = new MyModel();
>             $model->save($form->getValues());
>             $this->_redirect('/');
>         //} else { <--line removed
>         //    $form->populate($formData); <--line removed
>         }
>     } else {
>         $id = (int)$this->_request->getParam('id');
>         if ($id > 0) {
>             $model = new MyModel();
>             $formData = $model->get($id);
$form->setElementFilters(array()); <--line added
>             $form->populate($formData);
>         }
>     }

Here is why this works. Apparently (and I checked through the code to verify), the function isValid actually populates the form and filters all the values in the process. So if the filter actually modifies the value then you need to retrieve the modified value from the form. If you don't, then what is written to the database is the unfiltered value.

The other issue is that the function populate() also filters the values when populating the form. That may not seem like a problem except when your filter is such that multiple passes of the filter changes the data each time. For example, suppose I have an integer field in the form, and the filter is +1 (add one to the integer $value). Well, then what would happen is that clicking the link to edit populates the form and results in ($value + 1). This is because the link is not a post. So you see in the form not the number that is actually currently in the database, you see filtered value. When you click the button to save your changes, the value is filtered yet again. So saving results in $value + 2. Obviously this isn't a desired behavior. The only way I could see of enforcing that the edit view actually shows the current value in the database is to remove all the filters from the form before populating. Hence the line I added. setElementFilters() with an empty array serves to clear all the filters and set none.

Anyway, maybe some will benefit from this explanation of what I found.

Thanks everyone who responded.


--Seth

-----Original Message-----
From: Ed Lazor [mailto:edlazor@internetarchitects.biz]
Sent: Saturday, April 18, 2009 10:30 PM
To: Atkins, Seth (RICH1:5278); fw-mvc@lists.zend.com
Subject: Re: [fw-mvc] Form filters not working

Hi Seth,

Try

$model->save($form->getValues())

Let me know if that works for you.

-Ed


> Here is the code snippet from my controller that deals with editing forms.
> Tell me what I am doing wrong.
>
>     $form = new MyForm();
>     $form->submit->setLabel('Save');
>     $this->view->form = $form;
>     if ($this->_request->isPost()) {
>         $formData = $this->_request->getPost();
>         if ($form->isValid($formData)) {
>             $model = new MyModel();
>             $model->save($formData);
>             $this->_redirect('/');
>         } else {
>             $form->populate($formData);
>         }
>     } else {
>         $id = (int)$this->_request->getParam('id');
>         if ($id > 0) {
>             $model = new MyModel();
>             $formData = $model->get($id);
>             $form->populate($formData);
>         }
>     }

没有评论: