首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Symfony 2嵌入式表单集合多对多

Symfony 2嵌入式表单集合多对多
EN

Stack Overflow用户
提问于 2012-10-04 23:20:54
回答 1查看 5.5K关注 0票数 9

我有两个实体-用户和组。它们具有多对多关系,Group用于存储用户的角色。

我正在尝试通过添加集合来使用户编辑表单,我希望能够通过从下拉列表中选择一个新角色来添加它(仅限于数据库中已有的内容)

UserType.php:

代码语言:javascript
复制
class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('username')
            ->add('email')
            ->add('forename')
            ->add('surname')
            ->add('isActive')
            ->add('joinDate', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy'))
            ->add('lastActive', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy'))
            ->add('groups', 'collection', array(
                    'type' => new GroupType(),
                    'allow_add' => true,
                    ))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Sfox\CoreBundle\Entity\User'
        ));
    }
}

和GroupType.php:

代码语言:javascript
复制
class GroupType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('role');
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
                "data_class" => 'Sfox\CoreBundle\Entity\Group'
                ));
    }
}

这将在基本文本框中显示表单中的角色,但如果我在表单中添加一个条目,它会将一个新条目层叠保存到组中,如果我要编辑一个条目,它将更改底层的Group数据。

我试着做了一个GroupSelectType.php:

代码语言:javascript
复制
class GroupSelectType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('role', 'entity', array('class'=>'SfoxCoreBundle:Group', 'property'=>'name'));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
                "data_class" => 'Sfox\CoreBundle\Entity\Group'
                ));
    }
}

将字段添加为“实体”类型,这将显示正确的选择框(但使用默认值),我似乎无法将其绑定到UserType表单!

我想让表单做的就是修改用户实体中的底层'groups‘ArrayCollection。

有人知道我是如何做到这一点的吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-05 18:11:22

好吧,我想出了一个解决方案来解决任何其他类似的问题……

我必须创建一个自定义表单类型并将其声明为服务,这样我才能传入实体管理器。然后,我需要创建一个dataTransformer来将我的组对象更改为表单的整数

自定义GroupSelectType:

代码语言:javascript
复制
class GroupSelectType extends AbstractType

{
    /**
     * @var ObjectManager
     */
    private $om;

    private $choices;

    /**
     * @param ObjectManager $om
     */
    public function __construct(ObjectManager $om)
    {
        $this->om = $om;

        // Build our choices array from the database
        $groups = $om->getRepository('SfoxCoreBundle:Group')->findAll();
        foreach ($groups as $group)
        {
            // choices[key] = label
            $this->choices[$group->getId()] = $group->getName() . " [". $group->getRole() ."]";
        }
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new GroupToNumberTransformer($this->om);
        $builder->addModelTransformer($transformer);
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
                "choices" => $this->choices,
                ));
    }

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

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

在构造函数中,我将获取所有可用的组,并将它们放入一个“option”数组中,该数组将作为一个选项传递给选择框。

您还会注意到,我使用了一个自定义的数据转换器,这是为了将groupId (用于呈现表单)更改为组实体。我也将GroupSelectType作为服务,并传入了@doctrine.orm.entity_manager

services.yml (捆绑配置):

代码语言:javascript
复制
services:
    sfox_core.type.group_select:
        class: Sfox\CoreBundle\Form\Type\GroupSelectType
        arguments: [@doctrine.orm.entity_manager]
        tags:
          - { name: form.type, alias: group_select }

GroupToNumberTranformer.php

代码语言:javascript
复制
class GroupToNumberTransformer implements DataTransformerInterface
{
    /**
     * @var ObjectManager
     */
    private $om;

    /**
     * @param ObjectManager $om
     */
    public function __construct(ObjectManager $om)
    {
        $this->om = $om;
    }

    /**
     * Transforms an object (group) to a string (number).
     *
     * @param  Group|null $group
     * @return string
     */
    public function transform($group)
    {
        if (null === $group) {
            return "";
        }

        return $group->getId();
    }

    /**
     * Transforms a string (number) to an object (group).
     *
     * @param  string $number
     * @return Group|null
     * @throws TransformationFailedException if object (group) is not found.
     */
    public function reverseTransform($number)
    {
        if (!$number) {
            return null;
        }

        $group = $this->om
        ->getRepository('SfoxCoreBundle:Group')
        ->findOneBy(array('id' => $number))
        ;

        if (null === $group) {
            throw new TransformationFailedException(sprintf(
                    'Group with ID "%s" does not exist!',
                    $number
            ));
        }

        return $group;
    }
}

修改后的UserType.php -请注意,我现在使用的是自定义表单类型"group_select“,因为它是作为服务运行的:

代码语言:javascript
复制
class UserType extends AbstractType
{
    private $entityManager;

    public function __construct($entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new GroupToNumberTransformer($this->entityManager);

        $builder
            ->add('username')
            ->add('email')
            ->add('forename')
            ->add('surname')
            ->add('isActive')
            ->add('joinDate', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy'))
            ->add('lastActive', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy'));
        $builder
            ->add(
                $builder->create('groups', 'collection', array(
                    'type' => 'group_select',
                    'allow_add' => true,
                    'options' => array(
                            'multiple' => false,
                            'expanded' => false,
                            )
                    ))
        );
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Sfox\CoreBundle\Entity\User'
        ));
    }

    public function getName()
    {
        return 'sfox_corebundle_usertype';
    }
}
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12730544

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档