首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >zf2窗体和对象绑定,但不清除未传递的值

zf2窗体和对象绑定,但不清除未传递的值
EN

Stack Overflow用户
提问于 2012-12-25 18:32:13
回答 4查看 7.3K关注 0票数 4

我已经通读了Zend-Framework2中的表单组件的教程/参考,也许我错过了它,所以我在这里提问。

我有一个名为Node的对象,并将其绑定到一个表单。我用的是Zend\Stdlib\Hydrator\ArraySerializable标准饮水机。所以我的Node-object有exchangeArray()getArrayCopy()的两个方法,如下所示:

代码语言:javascript
复制
class Node
{
    public function exchangeArray($data)
    {
        // Standard-Felder
        $this->node_id        = (isset($data['node_id']))   ? $data['node_id']   : null;
        $this->node_name      = (isset($data['node_name'])) ? $data['node_name'] : null;
        $this->node_body      = (isset($data['node_body'])) ? $data['node_body'] : null;
        $this->node_date      = (isset($data['node_date'])) ? $data['node_date'] : null;
        $this->node_image     = (isset($data['node_image'])) ? $data['node_image'] : null;
        $this->node_public    = (isset($data['node_public'])) ? $data['node_public'] : null;
        $this->node_type      = (isset($data['node_type'])) ? $data['node_type']:null;
        $this->node_route      = (isset($data['node_route'])) ? $data['node_route']:null;
    }

    public function getArrayCopy()
    {
        return get_object_vars($this);
    }
}

在我的控制器中,我有一个editAction()。在这里,我想修改这个Node-object的值。因此,我使用的是表单的bind-method。我的表单只有用于修改node_namenode_body-property的字段。在验证表单并在提交表单后转储Node-object之后,node_namenode_body-properties现在包含来自提交的表单的值。然而,所有其他字段现在都是空的,即使它们以前包含初始值。

代码语言:javascript
复制
class AdminController extends AbstractActionController
{
    public function editAction()
    {
        // ... more stuff here (getting Node, etc)             

        // Get Form
        $form = $this->_getForm(); // return a \Zend\Form instance
        $form->bind($node); // This is the Node-Object; It contains values for every property

        if(true === $this->request->isPost())
        {
            $data = $this->request->getPost();
            $form->setData($data);

            // Check if form is valid
            if(true === $form->isValid())
            {
                // Dumping here....
                // Here the Node-object only contains values for node_name and node_body all other properties are empty
                echo'<pre>';print_r($node);echo'</pre>';exit;
            }
        }

        // View
        return array(
            'form' => $form,
            'node' => $node,
            'nodetype' => $nodetype
        );
    }
}

我只想覆盖来自表单(node_namenode_body)的值,而不是其他值。它们应该保持原样。

我认为一个可能的解决方案是将其他属性作为隐藏字段添加到表单中,但我不想这样做。

有没有可能不覆盖表单中不存在的值?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-12-27 06:21:24

我重新检查了\Zend\Form的代码,老实说,我只是猜测如何解决我的问题。

我唯一改变的就是饮水机。似乎Zend\Stdlib\Hydrator\ArraySerializable不是为我的情况而设计的。因为我的Node-Object是一个对象而不是数组,所以我检查了其他可用的other。我找到Zend\Stdlib\Hydrator\ObjectProperty-hydrator了。它工作得很完美。只有表单中可用的字段才会填充到绑定对象中。这正是我需要的。看起来像是ArraySerializable-hydrator重置了对象属性,因为它调用了绑定对象的exchangeArray-method (Node)。在此方法中,我将未给定的字段设置为null (请参阅我问题中的代码)。另一种方法可能是更改exchangeArray-method,以便仅在值还不可用时才设置这些值。

因此,代码中的解决方案很简单:

代码语言:javascript
复制
$form = $this->_getForm();
$form->setHydrator(new \Zend\Stdlib\Hydrator\ObjectProperty()); // Change default hydrator
票数 3
EN

Stack Overflow用户

发布于 2012-12-26 17:10:21

bindvalues类中存在错误,只需添加行$filter->setData($this->data);即可在form.php方法中不初始化筛选器

在包含下面这行之后,它应该如下所示

代码语言:javascript
复制
public function bindValues(array $values = array())
{
    if (!is_object($this->object)) {
        return;
    }
    if (!$this->hasValidated() && !empty($values)) {
        $this->setData($values);
        if (!$this->isValid()) {
            return;
        }
    } elseif (!$this->isValid) {
        return;
    }

    $filter = $this->getInputFilter();
    $filter->setData($this->data);          //added to fix binding empty data
    switch ($this->bindAs) {
        case FormInterface::VALUES_RAW:
            $data = $filter->getRawValues();
            break;
        case FormInterface::VALUES_NORMALIZED:
        default:
            $data = $filter->getValues();
            break;
    }

    $data = $this->prepareBindData($data, $this->data);

    // If there is a base fieldset, only hydrate beginning from the base fieldset
    if ($this->baseFieldset !== null) {
        $data = $data[$this->baseFieldset->getName()];
        $this->object = $this->baseFieldset->bindValues($data);
    } else {
        $this->object = parent::bindValues($data);
    }
}

更重要的是,它在我的zf2.0.6库中是第282行

这将解决您的问题,这只在绑定对象的情况下发生

票数 2
EN

Stack Overflow用户

发布于 2015-02-09 23:38:47

我遇到了同样的问题,但Raj的解决方案不是正确的方法。这不是一个bug,因为今天的代码在没有Raj的“修复”的情况下仍然保持相似,添加了一行:

代码语言:javascript
复制
$filter->setData($this->data);

这里的主要问题是,当您将对象绑定到表单时,inputfilter不会存储在表单对象中。而是每次从绑定的对象中调用。

代码语言:javascript
复制
public function getInputFilter()
    ...
    $this->object->getInputFilter();
    ...
}

我的问题是每次调用getInputFilter函数时都会创建一个新的InputFilter对象。因此,我将其更正为如下内容:

代码语言:javascript
复制
protected $filter;
...
public function getInputFilter {
    if (!isset($this->filter)) {
        $this->filter = new InputFilter();
        ...
    }
    return $this->filter;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14029821

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档