2017-07-17 20 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