Symfony 2.3.6. 嵌套表单

3
这个问题类似于这个,但有一个巨大的区别:我没有固定数量的要添加的元素。

以下是表单预览以及其应该看起来的样子。我有一个用户实体的表单,其中包含不同的应用程序实体,每个应用程序实体都有几个用户组实体

我的表单应该看起来的方式 - 嵌套实体

用户

class User extends BaseUser
{
...

/**
 * @ORM\ManyToMany(targetEntity="Application", inversedBy="users")
 * @ORM\JoinTable(name="users_applications")
 */
protected $applications;

/**
 * @ORM\ManyToMany(targetEntity="UserGroup", inversedBy="users")
 * @ORM\JoinTable(name="users_groups")
 */
protected $user_groups;

应用程序

class Application
{
...

/**
 * @ORM\ManyToMany(targetEntity="User", mappedBy="applications")
 */
protected $users;

/**
 * @ORM\OneToMany(targetEntity="UserGroup", mappedBy="application")
 */
protected $user_groups;

用户组

class UserGroup
{
...

/**
 * @ORM\ManyToOne(targetEntity="Application", inversedBy="user_groups")
 * @ORM\JoinColumn(name="application_id", referencedColumnName="id")
 */
protected $application;

/**
 * @ORM\ManyToMany(targetEntity="User", mappedBy="user_groups")
 */
protected $users;

UserFormType

class UserFormType extends AbstractType
{
    // Array of applications is generated in the Controller and passed over by the constructor
    private $applications;

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

    if ($this->applications && count($this->applications) > 0)
    {
        foreach ($this->applications AS $application)
        {
            $builder->add('applications', 'entity', array
            (
                'class' => 'MyBundle:Application',
                'property' => 'title',
                'query_builder' => function(EntityRepository $er) use ($application)
                {
                    return $er->createQueryBuilder('a')
                        ->where('a.id = :id')
                        ->setParameter('id', $application->getId());
                },
                'expanded' => true,
                'multiple' => true
            ));

            $builder->add('user_groups', 'entity', array
            (
                'class' => 'MyBundle:UserGroup',
                'property' => 'title',
                'query_builder' => function(EntityRepository $er) use ($application)
                {
                    return $er->createQueryBuilder('ug')
                        ->where('ug.application = :application')
                        ->setParameter('application', $application);
                },
                'expanded' => true,
                'multiple' => true
            ));
        }
    }
...

问题: 我已经成功地包含了应用程序用户组实体,但由于应用程序实体是通过循环添加到表单构建器中的,所以实体被覆盖,这样拥有多个应用程序时只有一个应用程序被呈现。


2
我们有一些类似的嵌套表单设置,但我们使用集合,也许这可以成为您问题的解决方案!http://symfony.com/doc/current/cookbook/form/form_collections.html - acrobat
你试图在每次迭代中添加相同的字段(应用程序名称)。这是不可能的。我建议为此字段创建特殊类型,带有实体子类型。 - zulus
1个回答

4

您需要集合。集合允许任意数量的元素(符合您的要求)。我认为问题在于您应该有一个UserGroupType,以便集合按照您想要的方式工作。

这里是您的表单类型的更为完整的示例。省略了命名空间和其他内容。

控制器(请记住,您正在向表单传递User对象,请勿像使用private $applications时那样操作):

...
$user = ...;
$form = $this->createForm(new UserFormType(), $user);

用户表单类型的更改:

class UserFormType extends AbstractType
{
    // Don't have that $applications member here...

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

        // Your user has many UserGroups, so display each one as a UserGroup field (see UserGroupFormType)
        $builder->add('user_groups', 'collection', array(
            'type'   => new UserGroupFormType()  // I would make this type a service (http://symfony.com/doc/current/book/forms.html#defining-your-forms-as-services)
        ));
    }

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

    // ... getname, etc.
}

新用户组表单类型:

class UserGroupFormType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // Each UserGroup has 1 application and multiple users
        // The entity fields allow you to select these

        $builder->add('application', 'entity', array
        (
            'class' => 'MyBundle:Application',
            'property' => 'title',
            'query_builder' => function(EntityRepository $er) use ($application)
            {
                return $er->createQueryBuilder('a')
                    ->where('a.id = :id')
                    ->setParameter('id', $application->getId());
            },
            'expanded' => true,
            'multiple' => false
        ));

        $builder->add('users', 'entity', array
        (
            'class' => 'MyBundle:User',
            'property' => 'title',
            'query_builder' => function(EntityRepository $er) use ($application)
            {
                return $er->createQueryBuilder('ug')
                    ->where('ug.application = :application')
                    ->setParameter('application', $application);
            },
            'expanded' => true,
            'multiple' => true
        ));
    }

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

    // ... getname, etc.
}

参见http://symfony.com/doc/current/cookbook/form/form_collections.html,该文档介绍了如何在表单中处理添加新的用户组(如果您需要该功能)。


感谢您的努力!您的解决方案中存在的问题是,我无法获得我想要的分层结构:1. 应用程序1;1.1. 组1;1.2. 组2;2. 应用程序2等。第二件事是,我编辑用户实体并希望选择应用程序/组 - 在您的解决方案中,我将编辑用户组实体。同时,我已将实体分配拆分为多个表单 - 但我将标记您的答案为已接受。 - Vilius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接