Symfony 3.x:形成1-N-1

时间:2018-01-10 12:25:34

标签: forms symfony

我正在尝试为具有子标记集合的媒体创建表单。根据学说文档,我创建了:

Test\CommonBundle\Entity\Media:
    type: entity
    table: media
    repositoryClass: Test\CommonBundle\Repository\MediaRepository
    indexes:
        index_title:
            columns: [ 'title' ]
    fields:
        id:
            type: integer
            id: true
            generator: { strategy: IDENTITY }
            nullable: false
        title:
            type: string
            nullable: false
            length: 200
    oneToMany:
        tagAssociate:
            targetEntity: Test\CommonBundle\Entity\TagAssociateMedia
            mappedBy: targetAssociate

Test\CommonBundle\Entity\TagAssociateMedia:
    type: entity
    table: tag_associate_media
    repositoryClass: Test\CommonBundle\Repository\TagAssociateMediaRepository
    fields:
        createdAt:
            type: datetime
            nullable: true
    manyToOne:
        targetAssociate:
            targetEntity: Test\CommonBundle\Entity\Media
            inversedBy: tagAssociate
            joinColumn:
                name: target_id
                referencedColumnName: id
        tag:
            targetEntity: Test\CommonBundle\Entity\TagMedia
            inversedBy: tagAssociate
            joinColumn:
                name: tag_id
                referencedColumnName: id

Test\CommonBundle\Entity\TagMedia:
    type: entity
    table: tag_media
    repositoryClass: Test\CommonBundle\Repository\TagMediaRepository
    indexes:
        index_name:
            columns: [ 'name' ]
    fields:
        id:
            type: integer
            id: true
            generator: { strategy: IDENTITY }
            nullable: false
        name:
            type: string
            nullable: false
            length: 100
    oneToMany:
        tagAssociate:
            targetEntity: Test\CommonBundle\Entity\TagAssociateMedia
            mappedBy: tag

我创建实体。例如,我有媒体:

<?php
namespace Test\CommonBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;

use \Test\CommonBundle\Entity\TagAssociate;

/**
* Media
*/
class Media
{
    /**
     * @var integer
     */
    protected $id;

    /**
     * @var string
     */
    protected $title;

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    protected $tagAssociate;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->tagAssociate = new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title
     *
     * @param string $title
     *
     * @return Media
     */
    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

    /**
     * Get title
     *
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }


    /**
     * Add tagAssociate
     *
     * @param \Test\CommonBundle\Entity\TagAssociate $tagAssociate
     *
     * @return Media
     */
    public function addTagAssociate(TagAssociate $tagAssociate)
    {
        $this->tagAssociate[] = $tagAssociate;

        $tagAssociate->setTargetAssociate($this);

        return $this;
    }

    /**
     * Remove tagAssociate
     *
     * @param \Test\CommonBundle\Entity\TagAssociate $tagAssociate
     */
    public function removeTagAssociate(TagAssociate $tagAssociate)
    {
        $this->tagAssociate->removeElement($tagAssociate);
    }

    /**
     * Get tagAssociate
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getTagAssociate()
    {
        return $this->tagAssociate;
    }
}

我在同一模型上创建TagMedia,并使用$ targetAssociate和$ tag attributs及其getter / setter创建中间实体。 到现在为止,我可以毫无问题地操纵我的实体。

现在问题是,我尝试创建一个这样的表单:

<?php
namespace Test\BackBundle\Entity\Form\Type;

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

use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;

use Symfony\Component\Form\FormInterface;

use Test\CommonBundle\Entity\Media;

class MediaType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options){
        $builder
            ->add('title', TextType::class, array(
                'label' => 'entity.media.title',
                'required' => true,
            ))
            ->add('tagAssociate', CollectionType::class, array(
                'label' => 'entity.tagAssociate',
                'required' => false,
                'entry_type' => TagAssociateType::class,
                'allow_add'    => true,
                'allow_delete' => true,
            ))
        ;

    }

    public function configureOptions(OptionsResolver $resolver){
        $resolver->setDefaults(array(
            'data_class' => Media::class,
            'translation_domain' => 'messages',
            'validation_groups' => function (FormInterface $form) {
                $data = $form->getData();
                $id = $data->getId();

                if( $id ){
                    return array('update');
                }

                return array('Default');
            },
        ));
    }

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

和子表格:

<?php
namespace Test\BackBundle\Entity\Form\Type;

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

use Symfony\Component\Form\FormInterface;

use Test\CommonBundle\Entity\TagAssociateMedia;

class TagAssociateType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options){
        $builder
            // what i am suppose to add here ?
            ->add('tag', EntityType::class, array(
                'class' => TagMedia::class,
                'label' => 'entity.tag',
                'required' => false,
                'choice_label' => 'name',
            ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver){
        $resolver->setDefaults(array(
            'data_class' => TagAssociateMedia::class,
            'translation_domain' => 'messages',
            'validation_groups' => function (FormInterface $form) {
                $data = $form->getData();
                $id = $data->getId();

                if( $id ){
                    return array('update');
                }

                return array('Default');
            },
        ));
    }

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

有了这个,我没有错误,我有0和1显示(在{{ form_row(form.tagAssociate) }}的枝条中),当我在这个屏幕中有2个关联时: enter image description here

但是当我想要这个时,我的问题就来了: enter image description here 我希望有一个与该关系对应的复选框列表,当我取消选中时,在更新时,将删除此关系(我将在JS中管理以添加与prototype和ajax请求的新关系以向服务器询问可用标记)。 / p>

知道我该怎么做吗?

2 个答案:

答案 0 :(得分:1)

您必须在表单中调用查询构建器来调用标记实体https://symfony.com/doc/current/reference/forms/types/entity.html#using-a-custom-query-for-the-entities 要删除,您只需使用您创建的特定方法取消设置Media Class中实体之间的关系。 使用Ajax发送标记id,获取逻辑中的Entity并删除关系

答案 1 :(得分:0)

我不明白为什么你有TagAssociateMedia。该实体不提供额外数据,它只是Media和TagMedia之间的桥梁。 如果是这种情况,您可以跳过TagAssociateMedia并将TagMedia添加为与Media的ManyToMany关系。 Doctrine将自己处理关联表。

这种方式很容易获得您想要的结果,只需在表单中添加字段:

->add('tagMedia', EntityType::class, array(
    'class' => 'TestCommonBundle:TagMedia',
    'multiple' => true,
    'expanded' => true,
    'required' => false
))