【问题标题】:zf2/zf3 Hydrate Multiple Fieldsets with Objectszf2/zf3 使用对象水合多个字段集
【发布时间】:2017-03-21 15:47:51
【问题描述】:

问题:使用 $form->bind($object) 时,表单中的多个字段集未填充/水合。您如何以 2 个不同的实体对象的形式填充 2 个不同的字段集? 我有 2 个字段集:FieldsetA、FieldsetB

一个表单 RegisterFrom 在它的 init() 方法中调用这些

class RegisterForm extends Form
{
    public function init(){
        $this->add(array(
                'name' => 'service_provider_fieldset',
                'type' => ServiceProviderFieldset::class,   // this is one model/entity
        ));

        $this->add(array(
                'name' => 'location_fieldset',
                'type' => LocationFieldset::class,   // this is a separate model/entity
        ));
}
}

创建字段集:(注意注释掉水合尝试)

class ServiceProviderFieldset extends Fieldset
{
    public function init(){
        //parent::__construct($name);
        /*
        $this
        ->setHydrator(new ClassMethodsHydrator(false))
        ->setObject(new ServiceProvider())
        ;
        */

        /*
        $this
        ->setHydrator(new ReflectionHydrator(false))
        ->setObject(new ServiceProvider())
        ;
        */

        $this->add(array(
                'type'=>'Hidden',
                'name'=>'id',
                'options'=>array(
                        'label' => 'Service Provider Id'
                ),
                'attributes'=>array(
                        'id'=>'providerId'
                )
        ));
}
}

控制器:

    $provider = $this->findServiceProviderById($providerId); // this is set from DB call and correctly creates a Provider() object with populated values.
    $location = $this->findServiceProviderLocationById($locId);
    $form = $formManager->get(RegisterForm::class);
    $form->bind($provider);
    $form->bin($location);
// $form->get('service_provider_fieldset')->bindValues(...);

查看:

$formElement = $form->get('service_provider_fieldset')->get('email');
etc...

表单在视图中正确呈现,但没有填充数据。

注意:不使用 Doctrine,但我从数据库中检索数据 OK。 注意:如果我设置此标志 'use_as_base_fieldset' => true, 然后填充 1 个对象(服务提供者),反之亦然,如果我将位置字段设置为 'true' 然后填充。 我一直在寻找几个小时,反复试验没有成功,我希望这只是我的疲劳,错过了一个简单的设置/配置步骤来让它工作。

总结:如何在一个表单中使用 2 个或更多实体填充 2 个或更多字段集? Bind(), fieldset->bindValues()?,

试过了:

$form->get('service_provider_fieldset')->allowObjectBinding(true);
        $form->get('service_provider_fieldset')->allowedObjectBindingClass(\Provider\Form\ServiceProviderFieldset::class);

这些是一些关闭但仍无法通过单独的实体填充两个字段集的链接。 ZF2 Form Hydration with multiple objects and fieldsets https://framework.zend.com/manual/2.4/en/modules/zend.form.collections.html hydrating multiple objects from fieldsets ZF2

集合(产品/品牌/类别)示例意味着使用 'use_as_base_fieldset' => true 的“单个”集合, 用于绑定()...?

【问题讨论】:

  • 更新:通过使用上面链接中的集合文档示例,我已经能够使该过程正常工作。使用模拟具有 1:1 、 1:many 关系的模型的单个字段集。但问题仍然存在 - 如何用不相关的对象填充两个或多个字段集的形式
  • 示例包括带有验证码的注册表单。我可以创建一个函数来直接将Recaptcha 添加到有效的表单中(但是我必须为每个表单重复此操作[或扩展抽象表单])
  • 您的问题解决了吗?我也有同样的……一个建议。当您从工厂检索字段集时,将使用表单的 init()。如果您只有简单的输入,您可以将它们包含在字段集或表单的 __construct() 方法中。
  • 没有这样解决。这是糟糕的设计吗?注意:我在视图中使用 prepare()。
  • 嘿,抱歉回复晚了。更新了我的答案,因为 cmets 中没有足够的空间。

标签: php zend-form zend-framework3 zend-form-fieldset


【解决方案1】:

在您的网页上,检查与您的字段集相关的表单元素名称。它们应该是这样的:yourFieldsetName[yourElementName]。如果您只看到yourElementName,那很可能意味着在视图脚本中忘记了prepare() 您的表单。

这正是发生在我身上的事情,在我prepare()ed 表单之后,所有的对象都被水合了,没有任何问题。

更新 = 回答评论问题:未解决。这是糟糕的设计吗?注意:我在视图中使用 prepare()。

如果一切正常,您的 2 个对象应该会补水。 use_as_base_fieldset 标志用于基本上说,'嘿,这就是我(字段集),你应该只用数据水合对象/从对象中提取数据'。所以你得到的一个物体被水合而另一个没有,反之亦然是可以预测的。如果不查看完整的代码,很难说出出了什么问题。恐怕发布太多也需要时间让回答者掌握,而我的经验是,此类问题通常无人回答。在像你这样的情况下,我通常会一步一步地使用 Zend Form's 和 Fieldsets 用于水合/提取的方法。我使用\Zend\Debug\Debug::dump($somethingThatYouWantToCheck); die();。这不是我认为的最佳方法,但它确实有效。

如果我是你,我也会这样做。

  1. 从您的帖子中,不清楚您为什么使用表单的init() 方法。 init() 方法用于您希望从 DB 中填充表单中的某些元素(如 <select>)。 Form 运行 init() 方法时,__construct() 方法中尚不可用,但仅在创建表单实例之后(不是 100% 确定这一点,请仔细检查)。

  2. 不用担心设计的好坏。设计是一件非常好的事情,但如果你有一个小型或中型系统,设计考虑不会影响系统的性能/复杂性。而是你会花很多时间做正确的事情,而不是仅仅做它,如果它工作正常,就忘记它。

  3. 如果您不想使用\Zend\Debug\Debug::dump($somethingThatYouWantToCheck); die();(我知道这可能很乏味),请创建一个字段集并将所需的 2 个字段集附加到它上面。然后在表单中包含此字段集并在此字段集上使用use_as_base_fieldset = true(当然,您还需要创建与此字段集相对应的对象,其中包含附加到当前字段集的 2 个嵌套对象,并将对象附加到字段集) .

希望这至少有一点帮助。

【讨论】:

    【解决方案2】:


    要处理您需要的多个对象:

    1. 为每个对象创建一个带有字段集的表单,就像您所做的那样。
    您必须为每个字段集指定一个名称(例如在构造函数中)。

    2. 在每个字段集中我们需要指定 hydrator
    例如:$this->setHydrator(new ClassMethods());

    Zend\Hydrator\ClassMethods 用于使用 getter 函数或
    Zend\Hydrator\ArraySerializable 用于使用 getArrayCopy 方法。

    并允许对象类:

    $this->setAllowedObjectBindingClass(YourClassObject::class);
    

    您可以在字段集中的 init 方法中完成。


    3.为主窗体设置水合器:

    $this->setHydrator(new ArraySerializable());
    


    4.现在在控制器方法中你可以创建 Zend\Stdlib\ArrayObject 的对象:

    $obj = new ArrayObject();
    

    然后使用等于字段集名称的键添加您的对象:

    $obj->offsetSet("fieldset_name", $your_object);
    

    然后您可以将 $obj 绑定到您的表单:

    $form->bind($obj);
    


    我希望这会有所帮助。并且不要忘记准备方法:

    return new ViewModel(["form" => $form->prepare()]);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      • 2017-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多