如何通过 SonataAdminBundle (Symfony) 管理 Doctrine ORM 类表继承?

Posted

技术标签:

【中文标题】如何通过 SonataAdminBundle (Symfony) 管理 Doctrine ORM 类表继承?【英文标题】:How to administer Doctrine ORM Class Table Inheritance via SonataAdminBundle (Symfony)? 【发布时间】:2017-12-05 09:37:21 【问题描述】:

我有一个 Doctrine-entity Foo 通过一对一模型与 AbstractBar Doctrine-entity 相关。

/**
 * @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;

AbstractBar 实体是一个抽象实体,两个特定实体使用 Class Table Inheritance 关联起来

所以,我有这个:

/**
 * @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

Foo实体的管理面板(SonataAdminBundle)配置如下:

class FooAdmin extends AbstractAdmin

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

同时,管理员类服务配置如下:

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

上面的代码允许我通过编辑 Foo 实体来编辑和创建 BarOne 实体。

我的问题是:如何才能在管理区域的BarOneBarTwo 之间切换?也就是说,这样我就可以实现 Doctrine ORM(类表继承)提供的多项选择。

【问题讨论】:

【参考方案1】:

为您的抽象 AbstractBar 类创建一个管理类,例如

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

    ...    

并为其定义服务,使用setSubclasses 调用来定义您的表/对象继承:

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]]

更新您的FooAdmin 以使用新创建的管理类:

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

BarAdmin 类中,您可以检查必须相应调整管理员的具体对象,例如配置表单域时

/**
 * @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 )
    

【讨论】:

感谢您的回答,很好地描述并与文档保持一致。但是,当我创建一个新的“Foo”时,它给了我一个错误:无法初始化抽象类:“MyBundle\Entity\AbstractBar”。有什么解决办法吗?

以上是关于如何通过 SonataAdminBundle (Symfony) 管理 Doctrine ORM 类表继承?的主要内容,如果未能解决你的问题,请参考以下文章

将自己的操作添加到 SonataAdminBundle 下拉菜单

SonataAdminBundle 如何获取当前的管理类?

SonataAdminBundle configureFormFields 与两步相关实体

如何在 SonataAdminBundle 的上传字段上方显示当前图片?

SonataAdminBundle 如何在列表视图中对列的值求和

如何仅在子管理员(SonataAdminBundle)中删除路由?