การส่งผ่านข้อมูลไปยัง buildForm () ใน Symfony 2.8, 3.0 ขึ้นไป


88

ขณะนี้แอปพลิเคชันของฉันส่งข้อมูลไปยังประเภทฟอร์มของฉันโดยใช้ตัวสร้างตามที่แนะนำในคำตอบนี้ อย่างไรก็ตามคู่มือการอัปเกรด Symfony 2.8แนะนำว่าการส่งอินสแตนซ์ประเภทไปยังcreateFormฟังก์ชันนั้นเลิกใช้แล้ว:

การส่งผ่านอินสแตนซ์ชนิดไปยัง Form :: add (), FormBuilder :: add () และเมธอด FormFactory :: create * () ถูกเลิกใช้และจะไม่ได้รับการสนับสนุนอีกต่อไปใน Symfony 3.0 ส่งชื่อคลาสแบบเต็มของชนิดแทน

Before:    
$form = $this->createForm(new MyType());

After:
$form = $this->createForm(MyType::class);

เมื่อเห็นว่าฉันไม่สามารถส่งผ่านข้อมูลด้วยชื่อคลาสที่มีคุณสมบัติครบถ้วนมีทางเลือกอื่นหรือไม่?


1
คุณต้องส่งข้อมูลประเภทใด เป็นสิ่งที่ฉีดได้หรือไม่?
Cerad

2
หวังว่า UPGRADE.md จะได้รับการปรับปรุง: github.com/symfony/symfony/issues/18662
althaus

คำตอบ:


134

สิ่งนี้ทำลายฟอร์มบางอย่างของเราเช่นกัน ฉันแก้ไขโดยส่งข้อมูลที่กำหนดเองผ่านตัวแก้ไขตัวเลือก

ในแบบฟอร์มของคุณ:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $this->traitChoices = $options['trait_choices'];

    $builder
        ...
        ->add('figure_type', ChoiceType::class, [
            'choices' => $this->traitChoices,
        ])
        ...
    ;
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'trait_choices' => null,
    ]);
}

จากนั้นเมื่อคุณสร้างแบบฟอร์มในคอนโทรลเลอร์ของคุณให้ส่งแบบฟอร์มเป็นตัวเลือกแทนในตัวสร้าง:

$form = $this->createForm(ProfileEditType::class, $profile, [
    'trait_choices' => $traitChoices,
]);

8
เพิ่งเจอปัญหานี้เช่นกันและทำวิธีแก้ปัญหาที่คล้ายกัน ฉันคิดว่าถ้าจำเป็นต้องใช้ข้อมูลและหากคุณต้องการทำชนิดของคำใบ้ที่คุณมักจะทำในนิยามตัวสร้างคุณควรใช้เมธอด setRequired () และ setAllowedTypes () สำหรับตัวแก้ไขตัวเลือกใน configurationOptions () ของคุณ แทน setDefaults ()
sarahg

2
นั่นคือสิ่งที่คุณควรทำ :)
Bernhard Schussek

3
@Roubi คุณทำสิ่งเดียวกันคุณกำหนดตัวเลือกในวิธีการกำหนดค่าตัวเลือกแล้วส่งผ่านเมื่อเพิ่มฟิลด์แบบฟอร์ม
Bart Wesselink

2
ฉันไม่พอใจกับการเปลี่ยนแปลงนี้เช่นกัน ขอบคุณสำหรับคำตอบว่า
Adambean

2
FormTypes ทำหน้าที่เหมือนโรงงานพวกเขาควรจะไร้สัญชาติ การใส่ค่าผ่านตัวสร้าง (นอกเหนือจากวิธีการแท็กบริการ) ทำให้เป็นสถานะ ด้วยวิธีนี้คุณมี 1 วิธีที่เหมือนกันในการสร้างประเภทฟอร์มของคุณ ตัวเลือกมักจะถูกนำมาใช้แทนอาร์กิวเมนต์ตัวสร้าง การเปลี่ยนแปลงนี้ดีมากสำหรับ DX และการใช้งาน
ทุกคนใน

6

ที่นี่สามารถใช้วิธีการอื่น - ฉีดบริการเพื่อดึงข้อมูล

  1. อธิบายแบบฟอร์มของคุณเป็นบริการ ( ตำราอาหาร )
  2. เพิ่มฟิลด์และตัวสร้างที่มีการป้องกันลงในฟอร์มคลาส
  3. ใช้ออบเจ็กต์ที่ถูกแทรกเพื่อรับข้อมูลที่คุณต้องการ

ตัวอย่าง:

services:
    app.any.manager:
        class: AppBundle\Service\AnyManager

    form.my.type:
        class: AppBundle\Form\MyType
        arguments: ["@app.any.manager"]
        tags: [ name: form.type ]

<?php

namespace AppBundle\Form;

use AppBundle\Service\AnyManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class MyType extends AbstractType {

    /**
     * @var AnyManager
     */
    protected $manager;

    /**
     * MyType constructor.
     * @param AnyManager $manager
     */
    public function __construct(AnyManager $manager) {
        $this->manager = $manager;
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $choices = $this->manager->getSomeData();

        $builder
            ->add('type', ChoiceType::class, [
                'choices' => $choices
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults([
            'data_class' => 'AppBundle\Entity\MyData'
        ]);
    }

}

นี่เป็นสิ่งที่ดี แต่จะไม่ได้ผลเมื่อไม่มีอาร์กิวเมนต์สำหรับผู้จัดการบริการ
demonkoryu

5

ในกรณีที่ใครก็ตามกำลังใช้ฟังก์ชัน 'createNamedBuilder' หรือ 'createNamed' จากบริการ form.factory นี่คือตัวอย่างวิธีการตั้งค่าและบันทึกข้อมูลโดยใช้ คุณไม่สามารถใช้ฟิลด์ 'data' (เว้นว่างไว้) และคุณต้องตั้งค่าข้อมูล / เอนทิตีที่ส่งผ่านเป็น$optionsค่า

ฉันยังรวมคำแนะนำ @sarahg เกี่ยวกับการใช้ตัวเลือก setAllowedTypes () และ setRequired () และดูเหมือนว่าจะทำงานได้ดี แต่ก่อนอื่นคุณต้องกำหนดฟิลด์ด้วย setDefined ()

นอกจากนี้ในแบบฟอร์มหากคุณต้องการตั้งค่าข้อมูลอย่าลืมเพิ่มลงในฟิลด์ 'ข้อมูล'

ในคอนโทรลเลอร์ฉันใช้ getBlockPrefix เนื่องจาก getName เลิกใช้งานใน 2.8 / 3.0

ตัวควบคุม:

/*
* @var $builder Symfony\Component\Form\FormBuilderInterface
*/
$formTicket = $this->get('form.factory')->createNamed($tasksPerformedForm->getBlockPrefix(), TaskAddToTicket::class, null, array('ticket'=>$ticket) );

แบบฟอร์ม:

public function configureOptions(OptionsResolver $resolver)    {
    $resolver->setDefined('ticket');
    $resolver->setRequired('ticket');
    $resolver->addAllowedTypes('ticket', Ticket::class);

    $resolver->setDefaults(array(           
        'translation_domain'=>'AcmeForm',
        'validation_groups'=>array('validation_group_001'),
        'tasks' => null,
        'ticket' => null,
    ));
}

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

    $this->setTicket($options['ticket']);
    //This is required to set data inside the form!
    $options['data']['ticket']=$options['ticket'];

    $builder

        ->add('ticket',  HiddenType::class, array(
                'data_class'=>'acme\TicketBundle\Entity\Ticket',
            )
        )
...
}

5

ต่อไปนี้เป็นวิธีส่งข้อมูลไปยังแบบฟอร์มที่ฝังไว้สำหรับทุกคนที่ใช้ Symfony 3 ขั้นแรกให้ทำตามที่ @sekl ระบุไว้ด้านบนจากนั้นทำสิ่งต่อไปนี้:

ใน FormType หลักของคุณ

ส่ง var ไปยังแบบฟอร์มที่ฝังโดยใช้ ' entry_options '

->add('your_embedded_field', CollectionType::class, array(
          'entry_type' => YourEntityType::class,
          'entry_options' => array(
            'var' => $this->var
          )))

ใน Embedded FormType ของคุณ

เพิ่มตัวเลือกให้กับ optionResolver

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'Yourbundle\Entity\YourEntity',
        'var' => null
    ));
}

เข้าถึงตัวแปรในฟังก์ชัน buildForm ของคุณ อย่าลืมตั้งค่าตัวแปรนี้ก่อนฟังก์ชันตัวสร้าง ในกรณีของฉันฉันต้องการกรองตัวเลือกตาม ID เฉพาะ

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $this->var = $options['var'];

    $builder
        ->add('your_field', EntityType::class, array(
          'class' => 'YourBundle:YourClass',
          'query_builder' => function ($er) {
              return $er->createQueryBuilder('u')
                ->join('u.entity', 'up')
                ->where('up.id = :var')
                ->setParameter("var", $this->var);
           }))
     ;
}

เพื่อให้มีความสับสนน้อยลง - $ this-> var คือค่าที่คุณต้องการส่งผ่านไม่จำเป็นต้องมาจากตัวแปรคลาส
Darius.V
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.