一个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值。
非常欢迎您提出建议。谢谢
答案 0 :(得分:1)
通常,如果关系/关联本身应具有属性,则原则中的多对多映射不再足够,因为关联无法存储其他数据。因此,您正确地注意到,您需要一个额外的AlphaBeta
实体/类来保存数据。 (正如Ali Kazemi已经发布的there is a tutorial for this)
但是您想知道如何将费用字段添加到表单中...
由于在您的情况下cost
是AlphaBeta
实体/类的一部分,因此表单字段的格式应为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;
使用常规的'getAlphaBeta
,addAlphaBeta
和removeAlphaBeta
方法。 (与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_field
是trick,让我将上面的表单用作表单中创建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关联,所以这没什么大不了的。
如果您看到我可以如何改进我的代码,欢迎您提出建议。