在Doctrine中使用抽象子类:好奇的数据库生成

时间:2015-09-07 14:17:30

标签: php mysql symfony doctrine-orm

我目前正在使用Doctrine2处理Symfony2 / mySQL项目。在我们的构想中,我们有一个超级"由抽象子类扩展的抽象类,它们本身由具体类扩展。

这是我的代码:

<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;

/**
 * Description of SuperAbstractClass
 *
 * @author gbrugiere
 * @ORM\Table(name="superabstractclass")
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string", length=2)
 * @ORM\DiscriminatorMap({"AC" = "AbstractClass","C1" = "ConcreteClass1", "C2" = "ConcreteClass2"})
 */
abstract class SuperAbstractClass {
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="label", type="text", nullable=false)
     */
    protected $label;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set libellé
     *
     * @param string $label
     * @return SuperAbstractClass
     */
    public function setLabel($label)
    {
        $this->label = $label;

        return $this;
    }

    /**
     * Get libellé
     *
     * @return string 
     */
    public function getLabel()
    {
        return $this->label;
    }
}
?>

然后:

<?php

namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of SuperAbstractClass
 *
 * @author gbrugiere
 * @ORM\Table(name="abstractclass")
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string", length=2)
 * @ORM\DiscriminatorMap({"C1" = "ConcreteClass1", "C2" = "ConcreteClass2"})
 */
abstract class AbstractClass extends SuperAbstractClass {

    /**
     * @var string
     *
     * @ORM\Column(name="souslibelle", type="text", nullable=false)
     */
    protected $sousLibelle;

    /**
     * Set sous-libellé
     *
     * @param string $sousLibelle
     * @return AbstractClass
     */
    public function setSousLibelle($sousLibelle)
    {
        $this->sousLibelle = $sousLibelle;

        return $this;
    }

    /**
     * Get sous-libellé
     *
     * @return string 
     */
    public function getSousLibelle()
    {
        return $this->sousLibelle;
    }
}
?>

这是我的最后一段代码:

<?php

namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of ConcreteClass1
 *
 * @author gbrugiere
 * @ORM\Table(name="concreteclass1")
 * @ORM\Entity
 */
class ConcreteClass1 extends AbstractClass {

    /**
     * @var string
     *
     * @ORM\Column(name="details", type="text", nullable=false)
     */
    private $details;

    /**
     * Set details
     *
     * @param string $details
     * @return ConcreteClass1
     */
    public function setDetails($details)
    {
        $this->details = $details;

        return $this;
    }

    /**
     * Get details
     *
     * @return string 
     */
    public function getDetails()
    {
        return $this->details;
    }
}
?>

当我生成我的SQL代码时,我得到:

CREATE TABLE superabstractclass (id INT AUTO_INCREMENT NOT NULL, libelle LONGTEXT NOT NULL, discr VARCHAR(2) NOT NULL, PRIMARY KEY(id)) 
DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
CREATE TABLE abstractclass (id INT NOT NULL, subLabel LONGTEXT NOT NULL, PRIMARY KEY(id)) 
DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
CREATE TABLE concreteclass1 (id INT NOT NULL, details LONGTEXT NOT NULL, PRIMARY KEY(id)) 
DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
CREATE TABLE concreteclass2 (id INT NOT NULL, detailsautres LONGTEXT NOT NULL, PRIMARY KEY(id)) 
DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;

ALTER TABLE abstractclass 
ADD CONSTRAINT FK_438A1A85BF396750 FOREIGN KEY (id) 
REFERENCES superabstractclass (id) ON DELETE CASCADE;

ALTER TABLE concreteclass1 
ADD CONSTRAINT FK_474E75CFBF396750 FOREIGN KEY (id) 
REFERENCES superabstractclass (id) ON DELETE CASCADE;

我对最后一行感到有些惊讶。为什么我的concreteclass1表引用了superabstractclass(请参阅*FK_474E75CFBF396750*)而不是abstractclass。我担心我的数据完整性:如果删除abstractclass行会发生什么。我仍然会有一个superabstractclass和一个concreteclass1行(意思是objet实例),但我会在我的对象上丢失一些信息。

我错过了什么吗?我现在已经找了好几个小时但却找不到任何东西。谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

我建议采用以下设置:

/**
 * @ORM\MappedSuperclass
 */
abstract class SuperAbstractClass {...}

/**
 * @ORM\MappedSuperclass
 */
abstract class AbstractClass extends SuperAbstractClass {...}

/**
 * @ORM\Table(name="concreteclass1")
 * @ORM\Entity
 */
class ConcreteClass1 extends AbstractClass {...}

这将在您的架构中创建一个表(名为concreteclass1),并具有Concrete,Abstract和SuperAbstractClass的所有属性。 您仍然可以使用通用功能(例如,ID生成将起作用)。

如果你有一个额外的ConcreteClass,它将创建一个新的表/实体,然后再次继承你需要的任何东西。

我们也有这样的设置 - 根据我的理解,这里不需要连接继承。