2013-10-30 49 views
4

在我的應用程序中,用戶可以爲某些實體創建自定義字段,然後在顯示錶單時爲每個實體對象設置此自定義字段的值。Symfony2表單事件PreSetData訂閱者

實現是這樣的:

1°),我創建了,我想實現這個接口的形式,並且形成了接口。

2º)我創建了所有形式的一種形式延伸:

app_core_form_builder.form_extension: 
     class: App\Core\Bundle\FormBuilderBundle\Form\FormExtension 
     arguments: ["@service_container", "@doctrine.orm.entity_manager"] 
     tags: 
      - { name: form.type_extension, alias: form } 

3º)在該分機如果窗體實施在步驟1中引用的接口I添加EventSubscriber:

if($formType instanceof \App\Core\Bundle\FormBuilderBundle\Model\IAllowCustomFieldsdInterface){ 
      $builder->addEventSubscriber(new FormSubscriber($this->container, $this->em));  
} 

4º)此表單訂閱者訂閱preSetData FormEvent。在這種方法中,我得到了與表單關聯的實體,並且我得到了爲它創建的所有自定義字段。 然後我在Symfony2 Form Type的幫助下將這些字段添加到表單中。 一切順利,當我顯示我的表單自定義字段呈現正確。只是爲了記錄,當我保存表單插入自定義字段中的值也存儲良好。

public function preSetData(FormEvent $event) { 

     $data = $event->getData(); 
     $form = $event->getForm(); 


     // During form creation setData() is called with null as an argument 
     // by the FormBuilder constructor. You're only concerned with when 
     // setData is called with an actual Entity object in it (whether new 
     // or fetched with Doctrine). This if statement lets you skip right 
     // over the null condition. 
     if (null === $data) { 
      return; 
     } 

     $formEntity = $form->getConfig()->getType()->getInnerType()->getEntity(); 

     $DbEntity = $this->em->getRepository('AppCoreSchemaBundle:DbEntity')->findOneBy(array('id' => $formEntity)); 

     if ($DbEntity && $DbEntity->getAllowCustomFields()) { 

      $organization = $this->container->get('app_user.user_manager')->getCurrentOrganization(); 

      if (!$organization) { 
       throw $this->createNotFoundException('Unable to find Organization entity.'); 
      } 

      $params = array(
       'organization' => $organization, 
       'entity' => $DbEntity, 
      ); 

      $entities = $this->em->getRepository('AppCoreSchemaBundle:DbCustomField')->getAll($params); 


      # RUN BY ALL CUSTOM FIELDS AND ADD APPROPRIATE FIELD TYPES AND VALIDATORS 
      foreach ($entities as $customField) { 
       # configurate customfield 

       FieldConfiguration::configurate($customField, $form); 
       # THE PROBLEM IS HERE 
       # IF OBJECT IS NOT NULL THEN MAKE SET DATA FOR APPROPRIATED FIELD 
       if ($data->getId()) { 

        $filters = array(
         'custom_field' => $customField, 
         'object' => $data->getId(), 
        ); 

        $DbCustomFieldValue = $this->em->getRepository('UebCoreSchemaBundle:DbCustomFieldValue')->getFieldValue($filters); 
       if ($DbCustomFieldValue) { 
        $form[$customField->getFieldAlias()]->setData($DbCustomFieldValue->getValue()); 
       } else { 
        $form[$customField->getFieldAlias()]->setData(array()); 
       } 
       } 
      } 
     } 
    } 

問題是當我嘗試編輯表單。如果你看看上面代碼中的「問題在這裏」部分,你可以理解。

如果表單的對象有一個ID,那麼我將獲得爲該對象的自定義字段存儲的值,並且我調用$ form [field_alias'] - > setData(從數據庫返回的值被映射爲類型數組)。

但是這不工作,並沒有設置數據的字段。但如果在我的控制器中,我也是這樣做的,那麼數據的設置是正確的。

有沒有人有問題可以在哪裏?我不能在preSetData事件中設置數據嗎?

EDITED

從實體DbCustomField值字段以這種方式被映射:

/** 
    * @var string 
    * 
    * @ORM\Column(name="value", type="array", nullable=true) 
    */ 
    protected $value; 

`

var_dump($DbCustomFieldValue) - >對象(UEB \核心\捆綁\ SchemaBundle \實體\ DbCustomFieldValue)

var_dump(DbCustomFieldValue->getValue()) 

- >字符串(11) 「布魯諾勇氣」

但是即使我嘗試類似:

var_dump($customField->getFieldAlias()); =字符串(21) 「testebruno-1383147874」

$form[$customField->getFieldAlias()]->setData('example1');它不工作。

但在我的控制,如果我做了上述fieldAlias如下:

$form['testebruno-1383147874']->setData('example2'); 

- >它的工作

任何想法?

+1

我沒有看到你的代碼幹啥交流中心,嘗試用模具調試它(的var_dump($數據)),所以我們可以看到什麼是你的數據陣列值 – metalvarez

+0

@ metalvarez檢查我的編輯 –

+2

前幾天我交叉相同的問題,我設法解決它通過更改表單事件,當您設置preSetData事件中的值然後symfony2將設置數據,它可能會改變你設置在preSetData事件之前,如果可以,請將事件更改爲postSetData,多數民衆贊成我如何解決它,所以我希望這將工作爲你。 – metalvarez

回答

1

作爲metalvarez建議in his/her commentworking as expected,使用postSetData事件而不是preSetData之一:

public function postSetData(FormEvent $event) { 
    // ... 
} 

preSetData事件方法與默認值填充表單之前調用,那麼Symfony2的將設置數據,並將其可能會改變你之前設置的內容,因此改爲使用postSetData

enter image description here

from the doc