Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8280325
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 8, 20262026-06-08T09:38:10+00:00 2026-06-08T09:38:10+00:00

Im playing around with Symfony2 and Im abit unsure how Symfony2 handles Polymorphic collections

  • 0

Im playing around with Symfony2 and Im abit unsure how Symfony2 handles Polymorphic collections in the View component. It seems that i can create an entity with a collection of AbstractChildren, but not sure how to what to do with it inside a Form Type class.

For example, I have the following entity relationship.

/**
 * @ORM\Entity
 */
class Order
{
    /**
     * @ORM\OneToMany(targetEntity="AbstractOrderItem", mappedBy="order", cascade={"all"}, orphanRemoval=true)
     * 
     * @var AbstractOrderItem $items;
     */
    $orderItems;  
    ...
}


/**
 * Base class for order items to be added to an Order
 *
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({
 *     "ProductOrderItem" = "ProductOrderItem",
 *     "SubscriptionOrderItem " = "SubscriptionOrderItem "
 * })
 */
class AbstractOrderItem
{
    $id;
    ...
}

/**
 * @ORM\Entity
 */
class ProductOrderItem  extends AbstractOrderItem
{
    $productName;
}

/**
 * @ORM\Entity
 */
class SubscriptionOrderItem extends AbstractOrderItem
{
    $duration;
    $startDate;
    ...
}

Simple enough, but when im create a form for my order class

class OrderType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->add('items', 'collection', array('type' => AbstractOrderItemType()));
    }
}

I am unsure how to handle this situation where you effectively need a different Form Type for each class of item in the collection?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-08T09:38:12+00:00Added an answer on June 8, 2026 at 9:38 am

    I recently tackled a similar problem – Symfony itself makes no concessions for polymorphic collections, but it’s easy to provide support for them using an EventListener to extend the form.

    Below is the content of my EventListener, which uses a similar approach to Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener, the event listener which provides the collection form type’s normal functionality:

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

    The downside to using this approach is that for it to recognize the types of your polymorphic entities on submit, you must set the data on your form with the relevant entities before binding it, otherwise the listener has no way of ascertaining what type the data really is. You could potentially work around this working with the FormTypeGuesser system, but that was beyond the scope of my solution.

    Similarly, while a collection using this system still supports adding/removing rows, it will assume that all new rows are of the base type – if you try to set them up as extended entities, it’ll give you an error about the form containing extra fields.

    For simplicity’s sake, I use a convenience type to encapsulate this functionality – see below for that and an example:

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

    Example:
    namespace Acme\VariedCollectionBundle\Form;

    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";
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

While playing around with the emulator, I noticed that when trying to view a
I've been playing around with Simple.Data and have run across something that I can't
playing around with a property file i figured that there seems to be a
Playing around with the ReadArgs package , it seems that it does not support
Playing around with MongoDB and NoRM in .NET. Thing that confused me - there
Been playing around with this for a couple of hours and can't seem to
Just playing around with some of the APIs in .NET and I can't seem
When playing around with multiprocessing I noticed that in the following script, __del__ is
I'm currently playing around with Symfony2 and like it very much so far. One
I am playing around with the AVAudioRecorder so I can have it in my

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.