2014-09-19 95 views
0

我使用entity表單類型來提供表單中的Position實體列表。我經常使用它(每個都有相同的「設置」代碼來定製它),我決定從中爲它創建一個自定義表單類型,以便更好地重用。Symfony2:自定義表單類型的動態默認值?

下面是當前表單類型:

class PositionType extends AbstractType 
{ 
    private $om; 

    public function __construct(ObjectManager $om, $mode) 
    { 
     $this->om = $om; 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     // I need to pass "mode" as an option when building the form. 
     $mode = ??? 
     $query_builder = function (EntityRepository $em) use ($mode) { 
      // Limit the positions returned based on the editing mode 
      return $em 
       ->createQueryBuilder('Position') 
       ->orderBy('Position.name') 
       ->leftJoin('Position.type', 'Type') 
       ->andWhere('Type.id IN (:ids)') 
       ->setParameter('ids', Type::typesForMode($mode)) 
      ; 
     }; 

     $resolver 
      ->setRequired(array('mode')) 
      ->setDefaults(array(
       'label' => 'Position', 
       'class' => 'AcmeBundle:Position', 
       'property' => 'name', 
       'query_builder' => $query_builder, 
       'empty_value' => '', 
       'empty_data' => null, 
       'constraints' => array(
        new NotBlank(), 
       ), 
      )) 
     ; 
    } 

    public function getParent() 
    { 
     return 'entity'; 
    } 

    public function getName() 
    { 
     return 'position'; 
    } 
} 

不要擔心在查詢生成器的細節,這並不重要。重要的部分是我試圖在查詢生成器中使用表單類型選項。

我該怎麼做?問題是我不能在setDefaultOptions中使用$mode(我想通過的選項來更改查詢生成器)。

我開始尋找一種方法從buildForm中設置查詢生成器,但我不確定我能做到這一點。

回答

1

這很容易實現。您可以構建一個取決於另一個選項的選項。

OptionResolver Component - Default Values that Depend on another Option

基本上,你會做什麼:

$resolver 
    ->setRequired(array('mode', 'em')) // "em" for EntityManager as well 
    ->setDefaults(array(
     'label' => 'Position', 
     'class' => 'AcmeBundle:Position', 
     'property' => 'name', 
     ##################################################### 
     'query_builder' => function(Options $options){ 
      // Obviously you will need to pass the EntityManager 
      $em = $options['em']; 

      // Limit the positions returned based on the editing mode 
      return $em 
       ->createQueryBuilder('Position') 
       ->orderBy('Position.name') 
       ->leftJoin('Position.type', 'Type') 
       ->andWhere('Type.id IN (:ids)') 
       ->setParameter('ids', Type::typesForMode($options['mode'])) // 
      ; 
     }, 
     #################################### 
     'empty_value' => '', 
     'empty_data' => null, 
     'constraints' => array(
      new NotBlank(), 
     ), 
    )) 
; 

這是一個什麼樣OptionsResolver能做的只是一個粗略的表示。希望它有幫助:)

+0

完美,正是我所需要的。謝謝。 – Brian 2014-09-19 17:20:18

+0

雖然我不是通過實體管理器,而是像最初一樣返回可調用的函數,它通過Symfony – Brian 2014-09-19 17:21:49

+0

的管理器正確地:)並歡迎您;) – 2014-09-19 18:57:58

0

您可以使用表單選項將變量傳遞到表單構建器。
例如在控制器中;

public function createAction() 
{ 
    $form = $this->formFactory->create('client', $client, array('name' => 'create')); 

    return $this->template->renderResponse('bundle:add.html.twig', array('form' => $form->createView())); 
} 

並在您的表單類型;

class PositionType extends AbstractType 
{ 
    private $mode; 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $this->mode = $options['name']; 
    } 


    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     // I need to pass "mode" as an option when building the form. 
     $mode = ??? 
     $query_builder = function (EntityRepository $em) use ($this->mode) { 
      // Limit the positions returned based on the editing mode 
      return $em 
       ->createQueryBuilder('Position') 
       ->orderBy('Position.name') 
       ->leftJoin('Position.type', 'Type') 
       ->andWhere('Type.id IN (:ids)') 
       ->setParameter('ids', Type::typesForMode($mode)) 
      ; 
     }; 

     $resolver 
      ->setRequired(array('mode')) 
      ->setDefaults(array(
       'label' => 'Position', 
       'class' => 'AcmeBundle:Position', 
       'property' => 'name', 
       'query_builder' => $query_builder, 
       'empty_value' => '', 
       'empty_data' => null, 
       'constraints' => array(
        new NotBlank(), 
       ), 
      )) 
     ; 
    } 
} 
+0

但'setDefaultOptions'之前調用'buildForm'? – Brian 2014-09-19 15:38:18

+0

@布賴恩你是正確的setDefaultOptions不會被首先調用。是否將變量傳遞給constrcutor給你一個選項? – Rooneyl 2014-09-19 15:44:51