Symfony 2.8, 3.0 ve üzeri sürümlerde buildForm () 'a veri aktarımı


87

Uygulamam şu anda bu yanıtta önerildiği gibi oluşturucuyu kullanarak form türüme veri aktarıyor . Bununla birlikte, Symfony 2.8 yükseltme kılavuzu , createFormişleve bir tür örneğini geçirmenin kullanımdan kaldırıldığını önerir :

Tip örneklerinin Form :: add (), FormBuilder :: add () ve FormFactory :: create * () yöntemlerine aktarılması kullanımdan kaldırılmıştır ve Symfony 3.0'da artık desteklenmeyecektir. Bunun yerine türün tam nitelikli sınıf adını iletin.

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

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

Tam nitelikli sınıf adıyla veri geçiremediğime göre, bir alternatif var mı?


1
Ne tür verileri iletmeniz gerekiyor? Enjekte edilebilecek bir şey mi?
Cerad

2
Umarım UPGRADE.md geliştirilir: github.com/symfony/symfony/issues/18662
2016

Yanıtlar:


133

Bu, bazı formlarımızı da kırdı. Özel verileri seçenekler çözümleyiciden geçirerek düzelttim.

Form türünüzde:

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,
    ]);
}

Ardından denetleyicinizde formu oluşturduğunuzda, kurucu yerine bir seçenek olarak iletin:

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

8
Sadece bu sorunla karşılaştım ve benzer bir çözüm yaptım. Bence veri gerekliyse ve yapıcı tanımında normalde yapacağınız türden ipucu vermek istiyorsanız, configureOptions () seçeneğinizdeki seçenekler çözümleyici için setRequired () ve setAllowedTypes () yöntemlerini kullanmalısınız. setDefaults () yerine.
sarahg

2
Yapman gereken tam olarak bu. :)
Bernhard Schussek

3
@Roubi aynı şeyi yaparsınız, configureOptions yönteminde bir seçenek tanımlar ve daha sonra bir form alanı eklerken bunu iletirsiniz.
Bart Wesselink

2
Ben de bu değişiklikten memnun değilim. Yine de cevap için teşekkürler.
Adambean

2
FormTypes fabrikalar gibi hareket eder, vatansız olmalıdır. Değerleri yapıcıları aracılığıyla enjekte etmek (servis etiketi yöntemi dışında), durumu durum bilgili kılar. Bu şekilde, form türünüzü oluşturmanın tek bir yoluna sahip olursunuz. Seçenekler her zaman yapıcı bağımsız değişkenleri yerine kullanılmak üzere tasarlanmıştır. Bu değişiklik DX ve kullanılabilirlik için harika.
herkes

6

Burada başka bir yaklaşım kullanılabilir - verileri almak için enjeksiyon hizmeti.

  1. Formunuzu hizmet olarak tanımlayın ( yemek kitabı )
  2. Sınıf oluşturmak için korumalı alan ve yapıcı ekleyin
  3. İhtiyacınız olan verileri almak için enjekte edilen nesneyi kullanın

Misal:

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'
        ]);
    }

}

Bu iyidir, ancak argüman servis yöneticisi için mevcut olmadığında işe yaramaz.
demonkoryu

5

Form.factory hizmetinden 'createNamedBuilder' veya 'createNamed' işlevlerinin kullanılması durumunda, verileri kullanarak verileri nasıl ayarlayıp kaydedeceğinize dair ön bilgi burada. 'Veri' alanını kullanamazsınız (boş bırakın) ve aktarılan verileri / varlıkları $optionsdeğer olarak ayarlamanız gerekir .

Ayrıca setAllowedTypes () ve setRequired () seçeneklerini kullanma hakkında @sarahg talimatlarını da ekledim ve iyi çalışıyor gibi görünüyor, ancak önce setDefined () ile alanı tanımlamanız gerekiyor

Ayrıca, verilerin ayarlanmasına ihtiyacınız varsa, formun içinde 'veri' alanına eklemeyi unutmayın.

Denetleyicide getBlockPrefix kullanıyorum çünkü getName 2.8 / 3.0'da kullanımdan kaldırıldı

Denetleyici:

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

Form:

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 kullanan herkes için verileri gömülü bir forma nasıl aktaracağınız aşağıda açıklanmıştır. Önce @sekl yukarıda özetlenen şeyi tam olarak yapın ve ardından aşağıdakileri yapın:

Birincil FormType'ınızda

Değişkeni ' entry_options ' kullanarak gömülü forma geçirin

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

Gömülü FormType'ınızda

Seçeneği seçeneklere ekleyin

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

BuildForm işlevinizdeki değişkene erişin. Bu değişkeni oluşturucu işlevinden önce ayarlamayı unutmayın. Benim durumumda, seçenekleri belirli bir kimliğe göre filtrelemem gerekiyordu.

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);
           }))
     ;
}

Daha az karışıklığa sahip olmak için - $ this-> var, mutlaka sınıf değişkeninden değil, geçmek istediğiniz değerinizdir.
Darius.V
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.