0
votes

I have a Doctrine-entity Foo that is related to the AbstractBar Doctrine-entity by the One-To-One model.

/**
 * @ORM\Table(name="foo")
 * @ORM\Entity
 */
class Foo
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var AbstractBar
     *
     * @ORM\OneToOne(targetEntity="AbstractBar", cascade={"persist"})
     * @ORM\JoinColumn(name="bar_id", referencedColumnName="id")
     */
    private $bar;
}

The AbstractBar entity is an abstract entity with which two specific entities are associated using Class Table Inheritance

So, I have this:

/**
 * @ORM\Table(name="bar")
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="bar_type", type="string")
 * @ORM\DiscriminatorMap({"one" = "BarOne", "two" = "BarTwo"})
 */
abstract class AbstractBar
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
}

/**
 * @ORM\Table(name="bar_one")
 * @ORM\Entity
 */
class BarOne extends AbstractBar
{
    // BarOne class properties
}

/**
 * @ORM\Table(name="bar_two")
 * @ORM\Entity
 */
class BarTwo extends AbstractBar
{
    // BarTwo class properties
}

The admin-panel (SonataAdminBundle) of the Foo entity is configured as follows:

class FooAdmin extends AbstractAdmin
{
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->add('bar', AdminType::class, array(), array(
                'admin_code' => 'key.of.bar_one.admin.service'
            ))
        ;
    }
}

At the same time, the administrator class service configuration looks like this:

key.of.bar_one.admin.service:
    class: MyBundle\Admin\BarAdmin
    arguments: [~, MyBundle\Entity\BarOne, ~]
    tags:
        - name: sonata.admin
          manager_type: orm
          show_in_dashboard: false

The above code allows me to edit and create BarOne entities by editing the Foo entity.

My question is: how can I make it so that I can switch between the BarOne and BarTwo in the admin area? That is, so that I can implement the multiple choice that is provided by the Doctrine ORM (Class Table Inheritance).

1

1 Answers

1
votes

create an admin class for your abstract AbstractBar class, e.g.

# MyBundle/Admin/BarAdmin.php
class BarAdmin extends AbstractAdmin
{
    ...    
}

and define a service for it, use the setSubclasses call to define your table / object inheritance:

key.of.bar.admin.service:
    class: MyBundle\Admin\AbstractBarAdmin
    arguments: [~, MyBundle\Entity\AbstractBar, SonataAdminBundle:CRUD]
    tags:
        - { name: sonata.admin, manager_type: orm, show_in_dashboard: false }
    calls:
        - [setSubclasses, [{'Bar One': MyBundle\Entity\BarOne, 'Bar Tow': MyBundle\Entity\BarTwo}]]

Update your FooAdmin to use the newly created admin class:

$formMapper
    ->add('bar', AdminType::class, array(), array(
        'admin_code' => 'key.of.bar.admin.service'
    ))
;

Inside of your BarAdmin class you can check which concrete object you have to adapt the admin accordingly, e.g. when configuring the form fields

/**
 * @param FormMapper $form
 */
protected function configureFormFields( FormMapper $form ) {
    $subject = $this->getSubject();

    // add shared fields
    $form->add();

    // BarOne fields
    if ( $subject instanceof BarOne )
    }

    // BarTwo fields
    if ( $subject instanceof BarTwo )
    }
}