子表单可以将值返回到父表单而不是对象吗?

时间:2014-07-11 13:45:18

标签: forms symfony

我看到Symfony2总是将表单类型绑定到对象,但是可以将表单类型重用到只能用作子项的位置吗?

这只是我试图完成的一个例子,但我认为它可以适用于许多场景。

首先让我说我有以下实体:

class Person
{
    public function getState();   
    public function getHomeState();   
}

这两个字段是州的选择字段。

我希望当用户选择选项getState()时,getHomeState()应该只返回一个字符串。

类似的东西:

<?php

namespace Acme\DemoBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;


class PersonFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('State', 'statelist'),//statelist is a form service.
            ->add('HomeState', 'statelist')//use form service here too
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\DemoBundle\Entity\Person'
        ));
    }

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

我遇到的问题是可以重复使用下面的表单。

<?php

namespace Acme\DemoBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class StateListType extends AbstractType
{
    protected $ChoiceList;

    public function __construct(ChoiceListInterface $Choices)
    {
        $this->ChoiceList = $Choices;
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //Unsure what to do here to accomplish what I want. 
        $builder->add(?, 'choice', array('choice_list' => $this->ChoiceList);
    }

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

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

问题是我不希望上面的表单与任何数据类绑定,只是让我重用那些为父表单提供字符串的选项。

这样我可以轻松地$Person->getState(),拥有字符串并完成它。

现在,如果我要使用另一个data_class作为上面的子表单,请说Address。其中包含一个同名的方法getState()。子表单会将Address对象返回到getState() Person方法,我必须分别通过$Person->getState()->getState()$Person->getHomeState()->getState()访问数据

这样做(从可读性的角度来看)是没有意义的,这适用于其他类似的用例。

是否可以让子表单只返回一个字符串给它的父表单而不是对象?

P.S。 我知道我可以单独使用选择列表,但选择列表不能用于服务。我必须包装&#39;将选择列表类转换为另一种形式,以便我可以将表单用作允许更大灵活性的服务。

1 个答案:

答案 0 :(得分:1)

是的,您可以将基本的“字符串”字段重新定义为“选择”而不添加内部字段,只需覆盖 setDefaultOptions ,关于 OptionResolverInterface 如何工作的一个很好的解释是{{ 3}}

<?php

namespace Acme\DemoBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class StateListType extends AbstractType
{
    protected $ChoiceList;

    public function __construct(ChoiceListInterface $Choices)
    {
        $this->ChoiceList = $Choices;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver
            ->setDefaults(
                array(
                    'choices' => $this->ChoiceList,
                    'empty_value' => 'select a state'
                )
            );

    }

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

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

另一种用于将对象转换为字符串的工具(但通常用于将字符串转换为对象)是将数据变换器添加到字段here

/**
 * {@inheritdoc}
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->addViewTransformer($this->createTransformer());
}

/**
 * @return DataTransformerInterface
 */
protected function createTransformer()
{
    return new FieldTransformer($this->getRepository(), static::FIELD_NAME);
}

但我认为这是另一个故事。需要了解的重要一点是,如果在formtype下添加字段,您的字段将返回一个对象(或我不记得的数组)而不是字符串