Symfony2:自定义表单类型的动态默认值?

时间:2014-09-19 15:15:26

标签: symfony

我使用entity表单类型来提供表单中Position个实体的列表。我经常使用它(每个都有相同的“设置”代码来定制它),我决定从中制作自定义表单类型以便更好地重复使用。

这是当前的表单类型:

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';
    }
}

不要担心查询构建器中的细节,这无关紧要。重要的部分是我正在尝试在查询构建器中使用表单类型选项。

我该怎么做?问题是我无法在$mode中使用setDefaultOptions(我希望传递以更改查询构建器的选项)。

我开始寻找一种从buildForm内部设置查询构建器的方法,但我不确定我能做到这一点。

2 个答案:

答案 0 :(得分: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可以做什么的粗略表示。希望它有所帮助:)

答案 1 :(得分: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(),
                ),
            ))
        ;
    }
}