सिम्फनी 2.8, 3.0 और इसके बाद के संस्करण के निर्माण के लिए डेटा पास करना


87

मेरा आवेदन वर्तमान में निर्माणकर्ता का उपयोग करके मेरे प्रपत्र प्रकार को डेटा पास करता है, जैसा कि इस उत्तर में अनुशंसित है । हालाँकि, सिम्फनी 2.8 अपग्रेड गाइड सलाह देता है कि createFormफ़ंक्शन के लिए एक प्रकार का उदाहरण देना पदावनत है:

फॉर्म को जोड़ने के उदाहरणों को पास करना :: जोड़ना (), फॉर्मब्यूलर :: ऐड () और फॉर्मफैक्टरी :: क्रिएट * () मेथड्स को अपग्रेड किया जाता है और सिम्फनी 3.0 में अब और सपोर्ट नहीं किया जाएगा। इसके बजाय पूरी तरह से योग्य वर्ग नाम पास करें।

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

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

यह देखकर कि मैं पूरी तरह से योग्य वर्ग के नाम के साथ डेटा पास नहीं कर सकता, क्या इसका कोई विकल्प है?


1
आपको किस प्रकार के डेटा को पास करने की आवश्यकता है? क्या यह ऐसा कुछ है जिसे इंजेक्ट किया जा सकता है?
सेराड

2
उम्मीद है कि UPGRADE.md बेहतर हो जाएगा: github.com/symfony/symfony/issues/18662
althaus

जवाबों:


133

इसने हमारे कुछ रूपों को भी तोड़ दिया। मैंने विकल्प रिज़ॉल्वर के माध्यम से कस्टम डेटा पास करके इसे ठीक किया।

अपने फार्म के प्रकार में:

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 () विधियों का उपयोग करना चाहिए। बजाय सेटडेफॉल्ट्स () के।
सारागह

2
ठीक यही आपको करना चाहिए। :)
बर्नहार्ड शुसेक 15

3
@Roubi आप एक ही काम करते हैं, आप कॉन्फ़िगर विकल्प विधि में एक विकल्प को परिभाषित करते हैं और फिर फॉर्म फ़ील्ड जोड़ते समय इसे पास करते हैं।
बार्ट वेसलिंक

2
मैं इस बदलाव से खुश नहीं हूं। जवाब के लिए धन्यवाद।
अदम्बियन

2
फॉर्मटेप्स कारखानों की तरह काम करते हैं, उन्हें स्टेटलेस होना चाहिए। उनके निर्माता (सेवा टैग विधि के माध्यम से अन्य) के माध्यम से मूल्यों को इंजेक्ट करना इसे स्टेटफुल बनाता है। इस तरह आपके पास अपना फॉर्म प्रकार बनाने का 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'
        ]);
    }

}

यह अच्छा है, लेकिन सेवा प्रबंधक के पास तर्क उपलब्ध नहीं होने पर काम नहीं करेगा।
डेन्कोरियो

5

मामले में किसी को भी 'createNamedBuilder' या 'createNamed' फ़ंक्शन का उपयोग कर रहा है form.factory सेवा यहाँ स्निपेट सेट करने और इसे उपयोग करने के डेटा को बचाने के लिए है। आप 'डेटा' फ़ील्ड का उपयोग नहीं कर सकते (उस शून्य को छोड़ दें) और आपको पारित डेटा / संस्थाओं को $optionsमूल्य के रूप में सेट करना होगा ।

मैंने setAllowedTypes () और setRequired () विकल्पों का उपयोग करने के बारे में @sarahg निर्देशों को शामिल किया और यह ठीक काम करने लगता है, लेकिन आपको पहले 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

यहाँ सिम्फनी 3 का उपयोग करने वाले किसी भी व्यक्ति को एक अंतर्निहित रूप में डेटा पास करने का तरीका बताया गया है। सबसे पहले ठीक वैसा ही करें जैसे @sekl ऊपर उल्लिखित किया गया है और फिर नीचे दिया गया है:

अपने प्राथमिक स्वरूप में

' Entry_options ' का उपयोग करके संस्करण को एम्बेडेड रूप में पास करें

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

अपने एंबेडेड फॉर्मटाइप में

विकल्प में विकल्प जोड़ें

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

अपने buildForm फ़ंक्शन में चर को एक्सेस करें। बिल्डर फ़ंक्शन से पहले इस चर को सेट करना याद रखें। मेरे मामले में मुझे एक विशिष्ट आईडी के आधार पर विकल्पों को फ़िल्टर करने की आवश्यकता थी।

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

कम भ्रम होने के लिए - $ यह-> var आपका मान है जिसे आप पास करना चाहते हैं, जरूरी नहीं कि वर्ग चर से।
डेरियस .V
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.