已解决- Symfony处理表单,并将存储库传入其中

bwntbbo3  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(91)

@更新如下

我读过https://symfony.com/doc/current/form/form_collections.html,它可以在这个文档中的一个例子中顺利工作。现在我想反向操作(零件->票证-用票证数据渲染零件)
我希望能够更新多个表单的数据,然后用一个按钮提交它。在这种情况下,每个部分都是单独的表单。现在我所实现的是将多个formView()放入一个数组中,然后呈现它-它具有来自数据库的数据,但这些是不同的表单:(.
主要的问题是,当我创建新的表单PartColletionType并向那里传递多个part对象时,它不会在页面上呈现它,但我可以添加新的PartsType表单。我假设问题要么与关系(ManyToOne -每个part只能有一个ticket)有关,要么与PartCollectionType的'data_class'有关。
Ticket.php

#[ORM\OneToMany(mappedBy: 'ticket', targetEntity: Part::class , cascade: ['persist'])]
private Collection $parts;

Part.php

#[ORM\ManyToOne(inversedBy: 'parts')]
private ?Ticket $ticket = null;

据我所知,这是一个包含其他形式的形式,所以我应该能够提交与按钮“UpdateAllParts”和学说的每一个孩子的形式将做其余的工作

class PartColletionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('UpdateAllParts' , SubmitType::class , [])
            ->add('partsType' , CollectionType::class , [
                'entry_type' => PartsType::class,
                'allow_add' => true,
                'mapped' => false,
                'allow_delete' => true
                ]);;
}
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            //I dont know if I have to set there data_class if yes which type?
            // 'data_class' => null,
            // 'data_class' => PartsType::class,
        ]);
    }
}
class PartsType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('submit' , SubmitType::class , [])
            ->add('partNumber' , TextType::class , [])
            ->add('distribution' , TextType::class , [])
            ->add('upsTrack' , TextType::class , [])
            ->add('returnalbe' , TextType::class , [])
            ->add('sendDate' , DateType::class , [])
            ->add('SOID' , TextType::class , [])
            //It's a form to display additional Part's Ticket data
            ->add('ticket' , TicketPartType::class , [
            ]);
 }
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Part::class,
        ]);
    }
}

部件附加:

class TicketPartType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('Institution')
            ->add('productName')
            ->add('productSerialNumber')
            ->add('externalTicketID')
            ->add('realisationTechnican' , EntityType::class , [
                'mapped' => true,
                'class' => Technican::class,
                'choice_label' => function (Technican $t): string {
                    return $t->getTechnicanSurname() . ' ' . $t->getCity();
                }]);
}

在控制器中,我传递多个票证

$parts = $doctrine->getRepository(Part::class)->findAll();
$parts = $formFactory->createNamed('ticketsparts' , PartColletionType::class , $parts);
        
return $this->renderForm('mba/ticketparts.html.twig' , ['parts' => $parts ]);

这是我的小树枝模板

{% macro printPartForm(partsType , productSerialNumber) %}
{{form(partsType)}}
{% endmacro %}
{% import _self as formMacros %}

<div class="parts0 row g-0" style="background:#CCC;"
data-index="{{ parts.partsType|length > 0 ? p.parts|last.vars.name + 1 : 0 }}"
data-prototype='{{ formMacros.printPartForm(parts.partsType.vars.prototype)|e('html_attr') }}'> 
    
    {% for part in parts.partsType %}
    <div class="row part" >
        {{ formMacros.printPartForm(part)}}
    </div>
    {% endfor %}

</div>

update所以现在我设置PartColletionType数据类为:

'data_class' => PartRepository::class
然后将Part repository传递到表单

$parts = $formFactory->createNamed('ticketsparts' , PartColletionType::class , $doctrine->getRepository(Part::class));

现在,在twig中,我可以通过调用传递给TWIG('parts')的参数的方法来访问所需的实体,并且所有内容都正确呈现。

{% form_theme parts 'bootstrap_5_layout.html.twig' %}
{{form_start(parts, {'attr': {'class':''}}) }}
{{form_row(parts.field_name)}}
{% for item in parts.findByExampleField %}  
<div class="row bg-warning m-5 ">
    <div class="div col-1 ps-2 pe-2 bg-warning">{{form_row(item.ticket.id)}}</div>
    <div class="div col-2 ps-2 pe-2 bg-warning">{{form_row(item.ticket.externalTicketID)}}</div>
    <div class="div col-1 ps-2 pe-2 bg-warning">{{form_row(item.returnalbe)}}</div>
    <div class="div col-1 ps-2 pe-2 bg-warning">{{form_row(item.sendDate)}}</div>
    <div class="div col-1 ps-2 pe-2 bg-warning">{{form_row(item.SOID)}}</div>
</div>
{% endfor %}
{{form_end(parts)}}

现在的问题是如何处理好它?

@Edit2ok.

if(isset($_POST['ticketsparts'])){
        $parts->handleRequest($request);

        if($parts->isSubmitted() && $parts->isValid()){
            var_dump('submitted and valid');
            $submittedParts= $parts->get('findByExampleField')->getData();

            foreach($submittedParts as $c){

                $doctrine->getManager()->persist($c);
            }
            $doctrine->getManager()->flush();
        }
    }

是不是很混乱?考虑到我们将repository传递给twig,它对性能有多大影响?在我的情况下,“selectByExampleField”将被限制在~100个实体,所以可能不会有问题,但每次编辑单个对象都会发送整个数据。
感谢您的帮助

brvekthn

brvekthn1#

所以...上面的分辨率是...不好的。你不能控制你想要显示的内容。所以让我们说-对于每一个排序方向,你必须制作单独的表单。
也许有人会发现这很有用。我在下面做了一些修改,其余的代码和上面的一样。
它确实呈现多个表单-单个部分与相关的门票数据,只需单击一下,我就可以提交多个部分。
//Controller.php

$collection_data = $doctrine->getRepository(Part::class)->findAll();
    $form = $this->createForm(PartColletionType::class , null , ['collection_data' => $collection_data]);
    
    if(isset($_POST['part_colletion'])){
        if(isset($_POST['part_colletion']['unsent']))
        {
            $collection_data = $doctrine->getRepository(Part::class)->findUnsentParts();
            $form = $this->createForm(PartColletionType::class , null , ['collection_data' => $collection_data]); 
            return $this->renderForm('mba/ticketparts.html.twig' , ['parts' => $form ]);
        }
        $form->handleRequest($request);
        if($form->isSubmitted() && $form->isValid()){
            $czesci = $form->get('collection')->getData();
            foreach($czesci as $c){
                $doctrine->getManager()->persist($c);
            }
            $doctrine->getManager()->flush();
        }
    } 
    return $this->renderForm('mba/ticketparts.html.twig' , ['parts' => $form ]);
}

//PartColletionType.php

class PartColletionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('submit' , SubmitType::class , [ 
                'attr' => ['class' => 'btn btn-success']])
            ->add('collection' , CollectionType::class , [
                'entry_type' => PartsType::class,
                'allow_add' => true,
                'mapped' => false,
                'data' => $options['collection_data'],
                ]);
;
    }
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => null,
            'collection_data' => null
        ]);
        $resolver->setAllowedTypes('collection_data', 'array');
    }
}
{% form_theme parts 'bootstrap_5_layout.html.twig' %}
{{form_start(parts, {'attr': {'class':''}}) }}
{{form_row(parts.submit)}}
{% for item in parts.collection %}  
<div class="row  m-5   {% if item.sendDate.vars.value is empty%}bg-danger {%else%} bg-success {% endif %}">
    <div class="div col-1 ps-2 pe-2">{{form_row(item.ticket.id)}}</div>
    <div class="div col-2 ps-2 pe-2">{{form_row(item.ticket.externalTicketID)}}</div>
    <div class="div col-1 ps-2 pe-2">{{form_row(item.sendDate)}}</div>
    <div class="div col-1 ps-2 pe-2">{{form_row(item.SOID)}}</div>
</div>
{% endfor %}
{{form_end(parts)}}

相关问题