मैंने हाल ही में एक समान समस्या का सामना किया - सिम्फनी स्वयं पॉलिमॉर्फिक संग्रह के लिए कोई रियायत नहीं देता है, लेकिन फ़ॉर्म का विस्तार करने के लिए इवेंट लिस्टनर का उपयोग करके उनके लिए समर्थन प्रदान करना आसान है।
namespace Acme\VariedCollectionBundle\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class VariedCollectionSubscriber implements EventSubscriberInterface
{
protected $factory;
protected $type;
protected $typeCb;
protected $options;
public function __construct(FormFactoryInterface $factory, $type, $typeCb)
{
$this->factory = $factory;
$this->type = $type;
$this->typeCb = $typeCb;
}
public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_SET_DATA => 'fixChildTypes'
);
}
public function fixChildTypes(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
// Go with defaults if we have no data
if($data === null || '' === $data)
{
return;
}
// It's possible to use array access/addChild, but it's not a part of the interface
// Instead, we have to remove all children and re-add them to maintain the order
$toAdd = array();
foreach($form as $name => $child)
{
// Store our own copy of the original form order, in case any are missing from the data
$toAdd[$name] = $child->getConfig()->getOptions();
$form->remove($name);
}
// Now that the form is empty, build it up again
foreach($toAdd as $name => $origOptions)
{
// Decide whether to use the default form type or some extension
$datum = $data[$name] ?: null;
$type = $this->type;
if($datum)
{
$calculatedType = call_user_func($this->typeCb, $datum);
if($calculatedType)
{
$type = $calculatedType;
}
}
// And recreate the form field
$form->add($this->factory->createNamed($name, $type, null, $origOptions));
}
}
}
:
नीचे मेरी EventListener, जो Symfony \ घटक \ फार्म \ एक्सटेंशन \ कोर \ EventListener \ ResizeFormListener, घटना श्रोता जो संग्रह प्रपत्र प्रकार की सामान्य सुविधा प्रदान करता है के लिए एक समान दृष्टिकोण का उपयोग करता है की सामग्री
इस दृष्टिकोण का उपयोग करने के लिए नकारात्मक पक्ष यह है कि इस पर अपनी बहुरूपी संस्थाओं के प्रकार की पहचान करने के लिए भेजने के बाद, आप चाहिए यह बाध्यकारी पहले संबंधित संस्थाओं के साथ अपने फार्म पर डेटा सेट किया गया है, नहीं तो श्रोता किस प्रकार पता लगाने का कोई तरीका नहीं डेटा वास्तव में है। आप FormTypeGuesser सिस्टम के साथ इस काम के आसपास संभावित रूप से काम कर सकते हैं, लेकिन यह मेरे समाधान के दायरे से बाहर था।
इसी प्रकार, जबकि इस प्रणाली का उपयोग करने वाला संग्रह अभी भी पंक्तियों को जोड़ने/हटाने का समर्थन करता है, तो यह मान लेगा कि सभी नई पंक्तियां मूल प्रकार के हैं - यदि आप उन्हें विस्तारित इकाइयों के रूप में सेट करने का प्रयास करते हैं, तो यह आपको एक त्रुटि देगा अतिरिक्त फ़ील्ड वाले फॉर्म के बारे में।
सादगी के लिए, मैं इस कार्यक्षमता को संपुटित करने के लिए एक सुविधा प्रकार का उपयोग करें - कि के लिए नीचे देखें और एक उदाहरण:
namespace Acme\VariedCollectionBundle\Form\Type;
use Acme\VariedCollectionBundle\EventListener\VariedCollectionSubscriber;
use JMS\DiExtraBundle\Annotation\FormType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\AbstractType;
/**
* @FormType()
*/
class VariedCollectionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Tack on our event subscriber
$builder->addEventSubscriber(new VariedCollectionSubscriber($builder->getFormFactory(), $options['type'], $options['type_cb']));
}
public function getParent()
{
return "collection";
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setRequired(array('type_cb'));
}
public function getName()
{
return "varied_collection";
}
}
उदाहरण: नाम स्थान एक्मे \ VariedCollectionBundle \ फार्म;
use Acme\VariedCollectionBundle\Entity\TestModelWithDate;
use Acme\VariedCollectionBundle\Entity\TestModelWithInt;
use JMS\DiExtraBundle\Annotation\FormType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\AbstractType;
/**
* @FormType()
*/
class TestForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$typeCb = function($datum) {
if($datum instanceof TestModelWithInt)
{
return "test_with_int_type";
}
elseif($datum instanceof TestModelWithDate)
{
return "test_with_date_type";
}
else
{
return null; // Returning null tells the varied collection to use the default type - can be omitted, but included here for clarity
}
};
$builder->add('demoCollection', 'varied_collection', array('type_cb' => $typeCb, /* Used for determining the per-item type */
'type' => 'test_type', /* Used as a fallback and for prototypes */
'allow_add' => true,
'allow_remove' => true));
}
public function getName()
{
return "test_form";
}
}
क्या आपको इस बारे में कोई जानकारी है कि सिम्फनी 2 के साथ काम करने के लिए इसे कैसे प्राप्त किया जाए? विशेष रूप से, "$ child-> getConfig() -> getOptions();" 2.0 में उपलब्ध नहीं है और इस तरह मैं फॉर्म के लिए मूल विकल्प नहीं प्राप्त कर सकता हूं। यदि मैं विकल्पों को छोड़ देता हूं तो मुझे अंततः "न तो संपत्ति" 0 "न ही विधि" get0() "न ही विधि" is0() "कक्षा में मौजूद है" सिद्धांत \ ORM \ PersistentCollection " – CriticalImpact
@CriticalImpact मैंने देखा है 2.0 फॉर्म घटक के लिए स्रोत, और मैं वास्तव में एक ही प्रभाव को प्राप्त करने के लिए कोई रास्ता नहीं देख सकता (विकल्प उसमें लंबी अवधि के लिए संग्रहीत नहीं हैं)। यदि आप साथ रह सकते हैं तो आप ऐसा करने में सक्षम हो सकते हैं हमेशा डिफ़ॉल्ट विकल्पों का उपयोग करके - जो त्रुटि आप ऊपर प्राप्त कर रहे हैं उसे हल करने के लिए, आपको केवल property_path को उचित रूप से सेट करना होगा (दुर्भाग्यवश मुझे संग्रह में संपत्ति पथों के लिए कौन सा स्वरूप 2.0 उपयोग करता है यह जानने के लिए मुझे इसे छोड़ना होगा - ए कुछ अच्छी तरह से रखा var_dump की चाल चलनी चाहिए, हालांकि) –
मैं वास्तव में एक और समाधान के साथ आने में कामयाब रहा। मैंने FormEvents :: PRE_SET_DATA के लिए एक ईवेंट श्रोता जोड़ा, बैकिंग ऑब्जेक्ट (मेरे मामले में एक प्रश्न ऑब्जेक्ट) मिला, जिस प्रकार का निर्धारण किया सवाल (मेरे पास मेरी क्यू में कुछ सेट है स्टियन जो कहता है कि यह एक चेकबॉक्स है, हां/नहीं, टेक्स्ट फ़ील्ड इत्यादि) और फिर प्रश्न ऑब्जेक्ट में सेट किए गए प्रकार के आधार पर फॉर्म में फ़ील्ड जोड़ा गया है। – CriticalImpact