Symfony 4.与属性的ManyToMany关联。自定义表格插入属性值,我该怎么办?

时间:2019-05-19 13:14:02

标签: symfony

一个Symfony 4项目。我看不到ho如何编写以下规范。

说我有两个实体Alpha和Beta。 创建Alpha对象alpha时,我希望将(ManyToMany)关联到一个或多个Beta对象。我知道如何呈现新内容并进行编辑。

我希望用一个属性(例如 Cost )丰富AlphaBeta连接表,以将Beta与Alpha相关联。问题是,当我创建一个Alpha对象并将其关联到Beta对象时,我无法丰富上述表格来插入或编辑 Cost 值。

是否存在编码这种情况的标准方法?

我读到要走的路是要有两个OneToMany关联Alpha-> ​​AlphaBeta和Beta-> AlphaBeta,但是即使这样做,我也无法为Alpha定义/渲染Form来创建新的Alpha对象,以将其与Beta对象(或更多)相关联,并为该关联分配一个Cost值。

非常欢迎您提出建议。谢谢

2 个答案:

答案 0 :(得分:1)

通常,如果关系/关联本身应具有属性,则原则中的多对多映射不再足够,因为关联无法存储其他数据。因此,您正确地注意到,您需要一个额外的AlphaBeta实体/类来保存数据。 (正如Ali Kazemi已经发布的there is a tutorial for this

但是您想知道如何将费用字段添加到表单中...

由于在您的情况下costAlphaBeta实体/类的一部分,因此表单字段的格式应为AlphaBetaType,这可能取决于所提供的选项-呈现AlphaType和/或BetaType子表单,以及cost表单字段。自定义表单主题可以某种方式显示它,如果担心的话,它看起来不会像子表单一样。 (不过,应注意的是,自定义表单主题有时会很烦人...)

通常,表单结构/层次结构通常非常类似于实体结构/层次结构。并且只能偶尔隐藏数据或对其进行映射/转换以不同方式显示或处理。

或者,您可以add an unmapped form field,然后将其存储在AlphaBeta中,但是平均起来并不简单,因为它涉及“手动”处理。

答案 1 :(得分:0)

看来我确实找到了一种方法,的确是非常简单的Synfony 4代码。
希望对别人有用。

(注意:我使用php bin/console make:entity/crud/form编写了所需的脚本。下面介绍了如何修改从make获得的代码)

所以说我有Alpha和Beta实体。 我希望有一个表单可以创建一个新的Alpha对象,将其与一个或多个Beta对象关联,并为每个Alpha-Beta关联填充Cost值。我也想要编辑表格。

首先,我创建一个新的AlphaBeta实体,其字段为:

 /**
 * @ORM\ManyToOne(targetEntity="App\Entity\Alpha", inversedBy="alphabetas", cascade={"persist"})
 * @ORM\JoinColumn(nullable=false)
 */
private $alpha;

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\Beta", inversedBy="betaalphas", cascade={"persist"})
 * @ORM\JoinColumn(nullable=false)
 */
private $beta;

 /**
 * @ORM\Column(type="string", length=255, nullable=true)
 */
private $cost;

我需要在Alpha类中

    /**
 * @ORM\OneToMany(targetEntity="App\Entity\AlphaBeta", mappedBy="alpha", orphanRemoval=true, cascade={"persist"})
 */
private $alphabetas;

使用常规的'getAlphaBetaaddAlphaBetaremoveAlphaBeta方法。 (与Beta类似)

我为新的AlphaBeta实体创建常规的CRUD控制器。为了拥有也可以用作子表单的AlphaBeta表单,我定义了

class `AlphaBetaEmbeddedForm`  extends AbstractType {

      public function buildForm(FormBuilderInterface $builder, array $options)
    {
    $builder ->add('Beta', EntityType::class, array(
                    'class' => Beta::class,
                    'multiple' => false,
                    'expanded' => true,
                    'choice_label' => 'betaTitle' ))
             ->add('cost', TextType::class);
   if(empty($options['remove_alpha_field'])) {
   $builder->add('Alpha', EntityType::class, array(
                   'class' => Alpha::class,
                   'multiple' => false,
                   'expanded' => true,
                   'choice_label' => 'alphaTitle'
    ));}}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => AlphaBeta::class,
        'remove_alpha_field' => false,
    ]);
}}

remove_alpha_fieldtrick,让我将上面的表单用作表单中创建Alpha对象的子表单:

class AlphaType extends AbstractType {

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

     $builder
        ->add('alphaTitle')       
        ->add('AlphaBetas', CollectionType::class, array(
           'entry_type'  => AlphaBetaEmbeddedForm ::class,
           'entry_options' => ['label' => true, 'remove_alpha_field' => true],
           'allow_add' => true,
           'label' => 'Betas',
           'by_reference' => false
    ));}

要在主表单中呈现子表单,我需要将一些JS,如建议的here插入new.html.twig的{​​{1}}和edit.html.twig模板中: / p>

Alpha

要应用后者,似乎您需要在主表单模板{% block javascripts %} <script type="text/javascript"> jQuery(document).ready(function () { $("#add-another-collection-widget").click(function(e){ var list = jQuery(jQuery(this).attr('data-list-selector')); var counter = list.data('widget-counter') | list.children().length; var newWidget = list.attr('data-prototype'); newWidget = newWidget.replace(/__name__/g, counter); counter++; list.data('widget-counter', counter); var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget); newElem.appendTo(list); });});</script>{% endblock %} 中写每一行:

_form.html.twig

仅此而已。

注意:在要编辑Alpha对象的主窗体中,我想为每个Beta相关对象插入一个删除按钮。据我所知,这是不可能的,因为这意味着在html表单中插入html表单。由于我可以通过相应的AlphaBeta删除操作删除AlphaBeta关联,所以这没什么大不了的。

如果您看到我可以如何改进我的代码,欢迎您提出建议。