Symfony2复选框列表

Symfony2复选框列表,symfony,checkbox,Symfony,Checkbox,我的项目中有一个多对多关系,但我想修改我的关系表,所以我将其转换为两个多对一关系,并在另一个实体上使用联接表 问题是,当我试图呈现两个初始实体的复选框组时,我无法使用它们 这是我的密码: class Professional extends User { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protecte

我的项目中有一个多对多关系,但我想修改我的关系表,所以我将其转换为两个多对一关系,并在另一个实体上使用联接表

问题是,当我试图呈现两个初始实体的复选框组时,我无法使用它们

这是我的密码:

class Professional extends User
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

...

/**
     * @ORM\OneToMany(targetEntity="TurnsProfessional", mappedBy="professional")
     */
    private $turns;

...
我的第二个实体

class Turn
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
...

  /**
     * @ORM\OneToMany(targetEntity="TurnsProfessional", mappedBy="turn")
     */
    private $professionals;

...
和join实体

class TurnsProfessional
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    public function __construct()
    {
    }

    /**
     * @ORM\ManyToOne(targetEntity="Turn", inversedBy="professionals")
     * @ORM\JoinColumn(name="turn_id", referencedColumnName="id")
     */
    private $turn;

    /**
     * @ORM\ManyToOne(targetEntity="Professional", inversedBy="turns")
     * @ORM\JoinColumn(name="professional_id", referencedColumnName="id")
     */
    private $professional;

    /**
     * @ORM\Column(type="boolean")
     */
    private $status = 0;
 ...
我的目标是在专业表单中创建一个带有轮次的复选框列表。我试过两件事:

首先,我尝试在ProfessionalType字段中添加一个Turn::class:

...
 ->add('turns', 'entity',
            array('class' => 'AppBundle:TurnsProfessional',
                'property' => 'label',
                'multiple' => true,
                'expanded' => true,
                ));
...
这里的问题是表单没有呈现复选框。否则,如果我更改类别:

...
->add('turns', 'entity',
            array('class' => 'AppBundle:Turn',
                'property' => 'label',
                'multiple' => true,
                'expanded' => true,
                ));
...
表单确实呈现了所有复选框,但我在发送时出错:

找到类型为AppBundle\entity\打开关联的实体 AppBundle\Entity\Professional#转身,但应为 AppBundle\Entity\TurnsProfessional

正如奥利弗(在评论中)所说,我编辑了表格:

使用TurnsProfessionalType

class TurnsProfessionalType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {  
        $builder
        ->add('status')
        ->add('turn', EntityType::class,
            array('class' => 'AppBundle:Turn',
                'property' => 'label',
                'multiple' => true,
                'expanded' => true,
             ));

    }

    public function getBlockPrefix()
    {
        return 'turns_professional_registration_form';
    }

    public function getName()
    {
        return $this->getBlockPrefix();
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => TurnsProfessional::class,
        ));
    }
}
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use AppBundle\Form\TurnsProfessionalType;

class ProfessionalType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('turns', CollectionType::class, array(
            'entry_type'   => TurnsProfessionalType::class,
            'allow_add' => true,
            'by_reference' => false, //with by_reference at false you force the call of the setter
        ))
            //other fields
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Professional',
            'cascade_validation => true //will also validate joined entities
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'turns_professional_registration_form';
    }
}
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use AppBundle\Entity\Turn;

class TurnsProfessionalType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('turn', EntityType::class, array(
            'class'   => Turn::class,
            'choice_label' => 'label'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\TypesProfessional'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'turns_professional_registration_form';
    }
}
现在我将其渲染为:

 {% for turn in form.turns %}
      <td><div class="checkbox">{{ form_widget(turn.status)}}<label></label></div></td>
    {% endfor %}
{%for turn in form.turns%}
{{form_小部件(turn.status)}
{%endfor%}
但我需要把每个回合的数据库标签作为标签

有人能帮忙吗? 谢谢大家!

专业实体

/**
 * @var ArrayCollection
 *
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\TurnsProfessional", mappedBy="professional", cascade={"persist"})
 */
private $turns;

public function __construct()
{
    $this->turns = new ArrayCollection();
}

/**
 * Add turn
 *
 * @param  TurnsProfessional $turns
 * @return Professional
 */
public function addTurn(TurnsProfessional $turn)
{
    /*
      Doctrine only checks the owning side(ManyToOne). So you
      need to manually call the join entity setter to keep
      your data in sync.
    */
    $turn->setProfessional($this);
    $this->turns->add($turn);

    return $this;
}

/**
 * Remove turn
 *
 * @param  TurnsProfessional $turn
 * @return Professional
 */
public function removeTurn(TurnsProfessional $turn)
{
    /*
      Doctrine only checks the owning side(ManyToOne). So you
      need to manually call the join entity setter to keep
      your data in sync.
    */
    $turn->setProfessional();
    $this->turns->removeElement($turn);

    return $this;
}

/**
 * Get turns
 *
 * @return ArrayCollection
 */
public function getTurns()
{
    return $this->turns;
}
/**
 * @var Professional
 *
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Professional", inversedBy="turns", cascade={"persist"})
 */
private $professional;

/**
 * @var Turn
 *
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Turn", inversedBy="professionals", cascade={"persist"})
 */
private $turn;

/**
 * @var bool
 *
 * @ORM\Column(name="status", type="boolean")
 */
private $status = true; //You should set a default value to true, since it is non sense to create some value if it not active

/**
 * Set professional
 *
 * @param Professional $professional
 * @return TurnsProfessional
 */
public function setProfessional(Professional $professional = null)
{
    /*
      Using a default null value allows you to unset of the value of
      the joined entity when removing in inverse side
      (see removeTurn in Professional entity)
    */
    $this->professional = $professional;

    return $this;
}

/**
 * Set turn
 *
 * @param Turn $turn
 * @return TurnsProfessional
 */
public function setTurn(Turn $turn = null)
{
    /*
      Using a default null value allows you to unset of the value of
      the joined entity when removing in inverse side
      (see removeProfessional in Turn entity)
    */
    $this->turn = $turn;

    return $this;
}
转向实体

/**
 * @var ArrayCollection
 *
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\TurnsProfessional", mappedBy="turn", cascade={"persist"})
 */
private $professionals;

public function __construct()
{
    $this->professionals = new ArrayCollection();
}

/**
 * Add professional
 *
 * @param TurnsProfessional $professional
 * @return Turn
 */
public function addProfessional(TurnsProfessional $professional)
{
    /*
      Doctrine only checks the owning side(ManyToOne). So you
      need to manually call the join entity setter to keep
      your data in sync.
    */
    $professional->setTurn($this);
    $this->professionals->add($professional);

    return $this;
}

/**
 * Remove professional
 *
 * @param TurnsProfessional $professional
 * @return Turn
 */
public function removeProfessional(TurnsProfessional $professional)
{
    /*
      Doctrine only checks the owning side(ManyToOne). So you
      need to manually call the join entity setter to keep
      your data in sync.
    */
    $professional->setTurn();
    $this->professional->removeElement($professional);

    return $this;
}

/**
 * Get professionals
 *
 * @return ArrayCollection
 */
public function getProfessionals()
{
    return $this->professionals;
}
专业实体的转变

/**
 * @var ArrayCollection
 *
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\TurnsProfessional", mappedBy="professional", cascade={"persist"})
 */
private $turns;

public function __construct()
{
    $this->turns = new ArrayCollection();
}

/**
 * Add turn
 *
 * @param  TurnsProfessional $turns
 * @return Professional
 */
public function addTurn(TurnsProfessional $turn)
{
    /*
      Doctrine only checks the owning side(ManyToOne). So you
      need to manually call the join entity setter to keep
      your data in sync.
    */
    $turn->setProfessional($this);
    $this->turns->add($turn);

    return $this;
}

/**
 * Remove turn
 *
 * @param  TurnsProfessional $turn
 * @return Professional
 */
public function removeTurn(TurnsProfessional $turn)
{
    /*
      Doctrine only checks the owning side(ManyToOne). So you
      need to manually call the join entity setter to keep
      your data in sync.
    */
    $turn->setProfessional();
    $this->turns->removeElement($turn);

    return $this;
}

/**
 * Get turns
 *
 * @return ArrayCollection
 */
public function getTurns()
{
    return $this->turns;
}
/**
 * @var Professional
 *
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Professional", inversedBy="turns", cascade={"persist"})
 */
private $professional;

/**
 * @var Turn
 *
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Turn", inversedBy="professionals", cascade={"persist"})
 */
private $turn;

/**
 * @var bool
 *
 * @ORM\Column(name="status", type="boolean")
 */
private $status = true; //You should set a default value to true, since it is non sense to create some value if it not active

/**
 * Set professional
 *
 * @param Professional $professional
 * @return TurnsProfessional
 */
public function setProfessional(Professional $professional = null)
{
    /*
      Using a default null value allows you to unset of the value of
      the joined entity when removing in inverse side
      (see removeTurn in Professional entity)
    */
    $this->professional = $professional;

    return $this;
}

/**
 * Set turn
 *
 * @param Turn $turn
 * @return TurnsProfessional
 */
public function setTurn(Turn $turn = null)
{
    /*
      Using a default null value allows you to unset of the value of
      the joined entity when removing in inverse side
      (see removeProfessional in Turn entity)
    */
    $this->turn = $turn;

    return $this;
}
职业型

class TurnsProfessionalType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {  
        $builder
        ->add('status')
        ->add('turn', EntityType::class,
            array('class' => 'AppBundle:Turn',
                'property' => 'label',
                'multiple' => true,
                'expanded' => true,
             ));

    }

    public function getBlockPrefix()
    {
        return 'turns_professional_registration_form';
    }

    public function getName()
    {
        return $this->getBlockPrefix();
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => TurnsProfessional::class,
        ));
    }
}
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use AppBundle\Form\TurnsProfessionalType;

class ProfessionalType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('turns', CollectionType::class, array(
            'entry_type'   => TurnsProfessionalType::class,
            'allow_add' => true,
            'by_reference' => false, //with by_reference at false you force the call of the setter
        ))
            //other fields
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Professional',
            'cascade_validation => true //will also validate joined entities
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'turns_professional_registration_form';
    }
}
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use AppBundle\Entity\Turn;

class TurnsProfessionalType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('turn', EntityType::class, array(
            'class'   => Turn::class,
            'choice_label' => 'label'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\TypesProfessional'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'turns_professional_registration_form';
    }
}
旋转专业类型

class TurnsProfessionalType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {  
        $builder
        ->add('status')
        ->add('turn', EntityType::class,
            array('class' => 'AppBundle:Turn',
                'property' => 'label',
                'multiple' => true,
                'expanded' => true,
             ));

    }

    public function getBlockPrefix()
    {
        return 'turns_professional_registration_form';
    }

    public function getName()
    {
        return $this->getBlockPrefix();
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => TurnsProfessional::class,
        ));
    }
}
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use AppBundle\Form\TurnsProfessionalType;

class ProfessionalType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('turns', CollectionType::class, array(
            'entry_type'   => TurnsProfessionalType::class,
            'allow_add' => true,
            'by_reference' => false, //with by_reference at false you force the call of the setter
        ))
            //other fields
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Professional',
            'cascade_validation => true //will also validate joined entities
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'turns_professional_registration_form';
    }
}
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use AppBundle\Entity\Turn;

class TurnsProfessionalType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('turn', EntityType::class, array(
            'class'   => Turn::class,
            'choice_label' => 'label'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\TypesProfessional'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'turns_professional_registration_form';
    }
}
小枝模板

/*
  By default you will have an empty turns collection which
  which means you will get no field displayed
  that's why you need a addTurn button to fill your collection
  and add fields to your form
*/ 
{{ form_start(form) }}
    <ul class="turns" data-prototype="{{ form_widget(form.turns.vars.prototype)|e('html_attr') }}">
        {% for turn in form.turns %}
            <li>{{ form_row(turn.turn) }}</li>
        {% endfor %}
    </ul>
{{ form_end(form) }}

<script>
    var $collectionHolder;

    // setup an "add a turn" link
    var $addTurnLink = $('<a href="#" class="add_turn_link">Add a turn</a>');
    var $newLinkLi = $('<li></li>').append($addTurnLink);

    jQuery(document).ready(function() {
        // Get the ul that holds the collection of turns
        $collectionHolder = $('ul.turns');

        // add the "add a turn" anchor and li to the turns ul
        $collectionHolder.append($newLinkLi);

        // count the current form inputs we have (e.g. 2), use that as the new
        // index when inserting a new item (e.g. 2)
        $collectionHolder.data('index', $collectionHolder.find(':input').length);

        $addTurnLink.on('click', function(e) {
            // prevent the link from creating a "#" on the URL
            e.preventDefault();

            // add a new turn form (see next code block)
            addTurnForm($collectionHolder, $newLinkLi);
        });
    });

    function addTurnForm($collectionHolder, $newLinkLi) {
        // Get the data-prototype explained earlier
        var prototype = $collectionHolder.data('prototype');

        // get the new index
        var index = $collectionHolder.data('index');

        // Replace '__name__' in the prototype's HTML to
        // instead be a number based on how many items we have
        var newForm = prototype.replace(/__name__/g, index);

        // increase the index with one for the next item
        $collectionHolder.data('index', index + 1);

        // Display the form in the page in an li, before the "Add a turn" link li
        var $newFormLi = $('<li></li>').append(newForm);
        $newLinkLi.before($newFormLi);
    }
</script>
/*
默认情况下,您将有一个空的turns集合
这意味着您将不会显示任何字段
这就是为什么你需要一个addTurn按钮来填充你的收藏
并将字段添加到表单中
*/ 
{{form_start(form)}}
    {%用于转入表单。转入%}
  • {{form_row(turn.turn)}
  • {%endfor%}
{{form_end(form)}} var$collectionHolder; //设置“添加转弯”链接 变量$addTurnLink=$(''); 变量$newLinkLi=$('
  • ).append($addTurnLink); jQuery(文档).ready(函数(){ //获取保存回合集合的ul $collectionHolder=$('ul.turns'); //将“添加转向”锚定和li添加到转向ul $collectionHolder.append($newLinkLi); //计算我们当前的表单输入(例如2),将其用作新的表单输入 //插入新项目时的索引(例如2) $collectionHolder.data('index',$collectionHolder.find(':input').length); $addTurnLink.on('click',函数(e){ //阻止链接在URL上创建“#” e、 预防默认值(); //添加新的转弯表单(请参见下一代码块) addTurnForm($collectionHolder,$newLinkLi); }); }); 函数addTurnForm($collectionHolder,$newLinkLi){ //获取前面解释的数据原型 var prototype=$collectionHolder.data('prototype'); //获取新索引 var索引=$collectionHolder.data('index'); //将原型HTML中的“\uuuu name\uuuuuu”替换为 //取而代之的是一个基于我们拥有多少物品的数字 var newForm=prototype.replace(/\uuuuu name\uuuuu/g,索引); //为下一项增加索引1 $collectionHolder.data('index',index+1); //在“添加一个回合”链接li之前,在页面中显示表格 变量$newFormLi=$('
  • ')。追加(newForm); $newLinkLi.before($newFormLi); }
    您应该使用a而不是EntityType,并查看@OlivierC上的symfony doc。我应该使用TurnsProfessional的CollectionType,还是TurnsProfessional?TurnsProfessional的CollectionType,具有EntityType字段的TurnsProfessional类型entity@OlivierC谢谢你,我设法走了这条路,问题是我无法访问回合的标签,以便能够渲染它。现在我把表格呈现在一个select上,上面有所有的数据库列。你的symfony版本是什么,所以我可以写一个合适的答案。你应该添加一些解释。