【问题标题】:Symfony2 + Twig: Using an entity type field to store unsaved entitiesSymfony2 + Twig:使用实体类型字段来存储未保存的实体
【发布时间】:2011-12-12 12:05:30
【问题描述】:

我花了一段时间浏览 symfony2 文档,试图找到一种合适的方法来做我需要做的事情,也许我找错地方了。

基本上,我有一个名为Album 的实体,它可以有许多Subalbums 与之关联。当用户使用表单创建Album 实体时,我希望他们能够在线创建快速Subalbum 实体,稍后将保存这些实体。我还想以自定义格式显示该字段,所以我不想使用带有 multiple 属性的 select 标签,而是在 Twig 中手动渲染它(我没有遇到问题这个)。

Subalbum上的关系定义如下:

/**
 * @ORM\ManyToOne(targetEntity="Vhoto\AlbumBundle\Entity\Album")
 * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
 */
protected $parent;

这是我迄今为止尝试过的......

  1. 在表单构建器中使用entity 类型字段,然后手动输出该字段。我在使用entity 字段时遇到的问题是,如果用户创建一个Subalbum 内联,symfony2 在我提交表单时不喜欢它,因为它没有 ID。

  2. 使用隐藏字段类型并尝试在同一字段名称 (album[subalbums][]) 下提交多个条目。 Symfony2 在我提交表单时也不喜欢这样

我想我必须在我的Album 实体中有一个prePersist 方法来创建用户已内联创建的任何Subalbum 实体?

希望有一个更优雅的解决方案,我只是完全忽略了。

如果有什么不清楚的地方请告诉我。

【问题讨论】:

    标签: php symfony twig


    【解决方案1】:

    确实有更好的方法。

    实体创建

    创建两个Entity POPO 并将many-to-one 关系分配给子实体的其中一个字段(您已正确完成此操作)。您可能还想在父级中定义one-to-many 关系

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="Child", mappedBy="parent", cascade={"persist", "remove" }, orphanRemoval=true)
     */
    protected $children;
    

    我不确定是否有必要,但您应该在设置器中明确设置关系以确保确定。例如在您拥有的实体中:

    public function addChild(ChildInterface $child)
    {
        if(!$this->hasChild($child))
        {
            $this->children->add($child);
            $child->setParent($this);
        }
    }
    

    Doctrine 可能不会使用这些方法来绑定帖子数据,但自己拥有它可能会解决几个持续存在的问题。

    表单类型创建

    为两个实体创建一个表单类型

    /**
     * This would be the form type for your sub-albums.
     */
    class ChildType extends AbstractType
    {
        public function buildForm(FormBuilder $builder, array $options)
        {
            //$builder->add(...);
            //...
        }
    
        public function getDefaultOptions(array $options) {
            return array(
                'data_class' => 'Acme\Bundle\DemoBundle\Entity\Child'
            );
        }
    
        public function getName()
        {
            return 'ChildType';
        }
    }
    
    /**
     * This would be the form type for your albums.
     */
    class ParentType extends AbstractType
    {
        public function buildForm(FormBuilder $builder, array $options)
        {
            // This part here describes the relationship between the two
            // form types.
            $builder->add('children', 'collection', array(
                'type' => new ChildType(),
                'allow_add' => true,
                'allow_delete' => true,
                'prototype' => true
            ));
        }
    
        public function getName()
        {
            return 'ChildType';
        }
    }
    

    使用allow_addallow_delete 选项,您有效地告诉Symfony,用户可以从集合中添加或删除实体。 prototype 选项可让您在页面上拥有所谓的子表单的原型。

    控制器

    为了安全起见,您也应该在此处强制执行关系。我已将其隐藏在单独的实体管理器层中(对于更复杂的实体,我有单独的管理器),但您当然也可以在控制器中执行此操作。

    foreach($parent->getChildren() as $child)
    {
        if($child->getParent() === NULL)
        {
            $child->setParent($parent);
        }
    }
    

    查看

    准备表单模板。原型应该通过在模板中的某处调用form_rest(form) 来呈现。如果没有,或者您想自定义原型,这里有一个示例说明如何进行。

    <script id="ParentType_children_prototype" type="text/html">
        <li class="custom_prototype_sample">
            <div class="content grid_11 alpha">
                {{ form_widget(form.children.get('prototype').field1) }}
                {{ form_widget(form.children.get('prototype').field2) }}
                {{ form_rest(form.children.get('prototype') ) }}
            </div>
        </li>
    </script>
    

    您必须使用 JavaScript 使表单动态化。如果您使用jQuery,您可以通过调用$('ParentType_children_prototype').html() 访问原型。向父级添加新子级时,务必将原型中所有出现的$$name$$ 替换为正确的索引号。

    我希望这会有所帮助。

    编辑我刚刚注意到有一个关于CollectionTypearticle in the Symfony2 Form Type reference。对于如何为此实现前端,它有一个很好的替代方案。

    【讨论】:

    • 多么棒的答案,我现在要努力实现这个......干杯
    • hmm,我收到一个错误Item "get" for "Array" does not exist,它指的是{{ form_widget(form.children.get('prototype').name) }} 行。我已经将构造函数中的subalbums 属性初始化为ArrayCollection,对吗?
    • 啊等等,我太傻了..我没有把children改成subalbums
    猜你喜欢
    • 2012-05-07
    • 2014-06-22
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    相关资源
    最近更新 更多