2017-07-17 36 views
3

我在表单类型中创建了一个属性(foo)。此属性的目标是将buildForm()方法(已初始化的位置以及PRE_SUBMIT侦听程序所在的位置已修改)的值传递给buildView()中的$view->vars如何处理表单类型的帮助属性?

这就是我想要做的(没有服务声明)样本:

class FooType extends AbstractType 
{ 
    private $foo; 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $this->foo = rand(0, 100); 

     $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { 
      $this->foo = rand(0, $event->getData()); 
     }); 
    } 

    public function buildView(FormView $view, FormInterface $form, array $options) 
    { 
     $view->vars['foo'] = $this->foo; 
    } 

    public function getParent() 
    { 
     return NumberType::class; 
    } 
} 

但这总是返回相同foo值的所有窗体字段,当我的预期相反。下面的屏幕截图显示了CollectionType 3个FooType条目:

screenshot

我不知道为什么!

public function configureOptions(OptionsResolver $resolver) 
{ 
    $resolver->setDefault('foo', rand(0, 100)); 
} 

,但我无法弄清楚如何修改当前此选项:另外,我用options还是当它(因为它仅用于内部目的)不会对我来说很有意义尝试形式方法。

如何正确实现它?

谢谢!

回答

2

该问题是由Symfony中所有表单类型(类)的自然状态条件引起的。当它没有被声明为服务时,每个实例只是一次。因此,除非需要像缓存配置这样的有状态行为,否则不要使用属性来满足这种需求。

解决方法

然而,为每个表格类型实例创建一个新的表单生成器实例,因此对于这类内部操作,您可以使用$builder->setAttribute()来代替。

注意:$builder->setAttribute()根本不是HTML属性,它只是关于表单配置属性。

例如内置CollectionTypeprototype属性有类似的情况:

namespace Symfony\Component\Form\Extension\Core\Type; 

// ... 

class CollectionType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     if ($options['allow_add'] && $options['prototype']) { 
      // ... 

      $builder->setAttribute('prototype', $prototype->getForm()); 
     } 
    } 

    public function buildView(FormView $view, FormInterface $form, array $options) 
    { 
     // ... 

     if ($form->getConfig()->hasAttribute('prototype')) { 
      $prototype = $form->getConfig()->getAttribute('prototype'); 
      $view->vars['prototype'] = $prototype->setParent($form)->createView($view); 
     } 
    } 
} 

但是,听众不必访问$builder->setAttribute(),所以对象的值需要一个标量,而不是能够修改属性。像这样的东西应该工作:

class FooType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->setAttribute('dummy', (object) array(
      'foo' => rand(0, 100), 
     )); 

     $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { 
      $dummy = $event->getForm()->getConfig()->getAttribute('dummy'); 
      $dummy->foo = rand(0, $event->getData()); 
     }); 
    } 

    public function buildView(FormView $view, FormInterface $form, array $options) 
    { 
     $view->vars['foo'] = $form->getConfig()->getAttribute('dummy')->foo; 
    } 

    // ... 
} 

查看更多about stateful or stateless classes in this article

+0

这工作,谢谢! – presto