Symfony2 doctrine声明实体使用单独的DB表维护继承

时间:2013-04-23 19:29:51

标签: inheritance symfony doctrine

我正在编写一个程序来跟踪客户可以订购的风帆。 我的程序有以下类结构:

Sail
    - mainsail
    - jib
    - spinnaker

我不确定是否使用mappedsuperclass或其他一些学说继承类型来维护程序中的以下类型的关系:

Mainsail extends Sail

我希望数据库本身(mySQL)分别有一个主帆,副臂和大三角帆表。

到目前为止,我的Co / QuoteBundle / Entity文件夹中只有一个Mainsail实体/类:

namespace Co\QuoteBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Mainsail
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Co\QuoteBundle\Entity\MainsailRepository")
 */
class Mainsail
{
    /**
     * @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=100)
     */
    private $name;

    /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="Boat", inversedBy="mainsails")
     * @ORM\JoinColumn(name="boat_id", referencedColumnName="id")
     * @Assert\NotBlank()
     */
    private $boatType;

    /**
     * @var float
     *
     * @ORM\Column(name="build_price", type="decimal")
     */
    private $buildPrice;

    //other variables, plus doctrine-generated getters and setters
}

最终,我的目标是能够不必为所有帆类重复相同的功能,这样我就可以将一个帆阵列发送到树枝中并在适用的地方将它们全部视为相同类型或不同类型

{% for sail in sails %}
    <p>{{sail.name}} (${{sail.buildPrice}})</p>
{% endfor %}

谢谢!

2 个答案:

答案 0 :(得分:0)

如果您希望每个表共享公共属性,那么class-table-inheritance是您的最佳选择:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#class-table-inheritance

这实际上取决于不同类型的帆之间存在多少差异。如果它只是几个属性,那么单表继承更快,可能适合您的需求。仔细阅读有关继承的章节。

答案 1 :(得分:0)

根据@ Cerad的回答,我提出了以下数据库架构:

sail {id (int), boat_id (int), discr (varchar), options (bool)}
mainsail {id (int), name (varchar), build_price (decimal), weight_lbs (decimal)}
jib {id (int), name (varchar), build_price (decimal), weight_lbs (decimal)}
spinnaker {id (int), name (varchar), build_price (decimal), weight_lbs (decimal)}

这是通过运行

生成的
$php app/console doctrine:generate:entities {packagename}
$php app/console doctrine:schema:update --force

关闭以下代码:

(doctrine从注释中生成discrimin列)

帆船类:

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity(repositoryClass="Co\QuoteBundle\Entity\SailRepository")
 * @ORM\Table(name="sail")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"main" = "Mainsail", "jib" = "Jib", "genoa" = "Genoa", "spinnaker" = "Spinnaker"})
 */
class Sail {

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

/**
 * @var integer
 *
 * @ORM\ManyToOne(targetEntity="Boat", inversedBy="sails")
 * @ORM\JoinColumn(name="boat_id", referencedColumnName="id", nullable=false)
 * @Assert\NotBlank()
 */
private $boatType;

/**
 * @var boolean
 *
 * @ORM\Column(name="options", type="boolean")
 */
private $hasOptions;

/**
* @ORM\OneToMany(targetEntity="SailOption", mappedBy="owningSail")
*/
private $optionChoices;

//setters and getters generated by doctrine

主帆级(悬臂和大三角帆是相同的):

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Mainsail
 *
 * @ORM\Table(name="mainsail")
 * @ORM\Entity(repositoryClass="Co\QuoteBundle\Entity\MainsailRepository")
 */
class Mainsail extends Sail {


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

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

/**
 * @var float
 *
 * @ORM\Column(name="build_price", type="decimal", precision=7, scale=2)
 */
private $buildPrice;

/**
 * @var float
 *
 * @ORM\Column(name="weight_lbs", type="decimal", precision=4, scale=1)
 */
private $weightLbs;

//getters and setters generated by doctrine

是的,name,build_price和weight变量存在冗余。我将它们留在不同的表中,因为我认为这是一个更好的方法,可以用于简单的CMS的未来开发,以单独添加/删除风帆。由于我没有解决这个问题,而且我对此仍然相对较新,我不确定是否会出现这种情况。评论赞赏:)

感谢。