帮助我理解Doctrine 2中的单类继承

时间:2011-04-29 11:27:21

标签: php orm doctrine-orm single-table-inheritance

<?php
namespace Jo\Model;

/**
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="resource_type", type="string")
 * @DiscriminatorMap({"article" = "\Jo\Model\Article\ArticleVote", "comment" = "\Jo\Model\Article\CommentVote"})
 */
class Vote
{
    /**
     * @Id
     * @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ManyToOne(targetEntity="\Jo\Model\User\User")
     */
    protected $user;


    /**
     * @Column(type="integer")
     */
    protected $weight;

    public function setWeight($weight)
    {
        $this->weight = $weight;

        return $this;
    }

    public function getWeight()
    {
        return $this->weight;
    }
}

<?php
namespace Jo\Model\Article;
use Jo\Model;
/**
 * @Entity
 */

class CommentVote extends Model\Vote
{
    /**
     * @ManyToOne(targetEntity="Comment")
     */
    protected $comment;

    public function setComment(Comment $comment)
    {
        $this->comment = $comment;

        return $this;
    }

    public function getComment()
    {
        return $this->comment;
    }
}

它生成以下表模式:

CREATE TABLE Vote (
   id INT AUTO_INCREMENT NOT NULL, 
   user_id INT DEFAULT NULL, 
   article_id INT DEFAULT NULL, 
   comment_id INT DEFAULT NULL, 
   weight INT NOT NULL, 
   resource_type VARCHAR(255) NOT NULL, 
INDEX IDX_FA222A5AA76ED395 (user_id), 
INDEX IDX_FA222A5A62922701 (article_id), 
INDEX IDX_FA222A5AF8697D13 (comment_id), 
PRIMARY KEY(id)
) ENGINE = InnoDB;

看起来是正确的。

然而,当我这样做时:

$commentVote = new CommentVote();
$commentVote->setComment($comment); // $comment instance of Comment
$commentVote->setWeight(1);
$em->persist($commentVote);
$em->flush();

我收到以下错误:

Message: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'resource_type' cannot be null 

我是否必须手动设置用作鉴别器的resource_type属性?如果我在两个不同的类上使用单表继承,我不会手动指出这一点。

我做错了什么,我找不到有关此类实施的任何有价值的信息。

哎呀。

2 个答案:

答案 0 :(得分:0)

CommentVote正在扩展投票。投票为resource_type。所以现在你必须为CommentVote设置它,它不能为null:

resource_type VARCHAR(255) NOT NULL

你必须说出你想要的resource_type。我无法猜到。

但是你可以在投票中设置为可以为空:

/**
 * @Column(type="string", length=255", nullable=true)
 */
private $resource_type;

或者您可以为resource_type设置默认值。如果是这样,您可以选择在CommentVote的__construct中设置默认值,或者也可以在@PreUpdate方法中设置该值。

答案 1 :(得分:0)

我遇到了类似的问题,但那是因为我这样做了:

<?php

/**
 * This class, although not abstract, is not intended to be instantiated, 
 * and so is not in the discriminator map.
 */
class BaseClass
{
     public static function create()
     {
          return new self();
     }
}

/**
 * This class is in the discriminator map.
 */
class SubclassOne
extends BaseClass
{
     // ...
}

$one = SubclassOne::create();
$em->persist($one);
$em->flush();

我的案例中的问题与Doctrine无关:​​因为self不使用后期绑定,我在不知不觉中获得了BaseClass而不是SubclassOne的实例。由于BaseClass没有鉴别器映射,因此无法通过Doctrine填充鉴别器列。

我已经摆脱了所有的::create()废话并开始使用常规构造函数,我也可能会使BaseClass抽象化。