Question

I'm building a form generator using Symfony 2.2 with Doctrine.

My entities are the following:

  • Form
  • WidgetText
  • WidgetSelect

All my widgets extend the following class:

/**
 * Widget
 *
 * @ORM\MappedSuperclass
 */
abstract class Widget
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Form", inversedBy="widgets")
     */
    private $form;

    /**
     * @var string
     *
     * @ORM\Column(name="type", type="string", length=255)
     */
    private $type;

    /**
     * @var integer
     *
     * @ORM\OneToOne(targetEntity="Question")
     */
    private $question;

    // getters and setters
}

My Form entity looks like this:

/**
 * Form
 *
 * @ORM\Table(name="form")
 * @ORM\Entity(repositoryClass="Ineat\FormGeneratorBundle\Entity\FormRepository")
 * @UniqueEntity("name")
 * @UniqueEntity("slug")
 */
class Form
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="slug", type="string", length=255)
     */
    private $slug;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="Widget", mappedBy="form")
     */
    private $widgets;


    public function __construct()
    {
        $this->widgets = new ArrayCollection();
    }

    // getters and setters
}

And one Widget entity:

/**
 * Widget
 *
 * @ORM\Table(name="widget_choices")
 * @ORM\Entity
 */
class WidgetChoices extends Widget
{
    /**
     * @var array
     *
     * @ORM\Column(type="array")
     */
    private $choices;

    // getters and setters
}

Whenever I try to display my form I've got the following error:

Neither property "WidgetText" nor method "getWidgetText()" nor method "isWidgetText()" exists in class "Ineat\FormGeneratorBundle\Entity\Form"

It seems it's like if my widgets weren't extending Widget at all. I need a way to cast my widgets as Widget or a way to tell doctrine that my ArrayCollection can contains everything extending Widget.

Is it possible?

Was it helpful?

Solution

Widget is a MappedSuperclass (no table) and Form has a 1-n key to it. Since every subclass of Widget will live in its own table, this is not a valid relation. Or in other words MappedSuperclass may not have a n-1 relation (think of it more like a decorator).

You could use the generic foreign key paradigm to do it like you wanted or use single table inheritance for the widget, which is better for your case (ref http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html#single-table-inheritance.)

table Widget(id, type)
table WidgetXY(id, X, Y)
table WidgetQR(id, Q, R)

A new WidgetXY entity would result in row of Widget(id=7, type=1) AND a row of WidgetXY(id=7, X, Y). A controller (doctrine) would identify a type=1 row referring to WidgetXY by using a discriminator map, on the database level you just join against the correct table, pkeys 1-1.

In doctrine you have to set the inheritance type to joined and define your discriminator map in the annotations (see link above)

hth

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top