2014-09-19 101 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