Symfony2 / Doctrine2继承

时间:2013-07-01 15:58:33

标签: symfony doctrine

我正在尝试在Doctrine 2中完成BASIC继承,但我遇到了几个主要问题。这样的任务不应该那么复杂。让我们开始做生意......

我有三个类,BaseFoodType,Drink和Snack。我的BaseFoodType具有以下类定义:

/** @ORM\MappedSuperclass */
class BaseFoodType {

    /**
     * @ORM\Column(type="integer", length=7)
     */
    public $budget = 0;
}

遵循学说网站上的继承说明:http://docs.doctrine-project.org/en/2.0.x/reference/inheritance-mapping.html

以下是生成实体之前子类的样子:

namespace MySite\MainBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * MySite\MainBundle\Entity\EventDrink
 *
 * @ORM\Table(name="drink")
 * @ORM\Entity
 */
class Drink extends BaseFoodType {

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

    /**
     * @ORM\Column(type="integer", length=5, nullable=true)
     */
    public $people_count;
}

Drink和Snack都继承自这个基类,但是当我尝试使用doctrine:generate:entities命令构建我的实体时,我遇到了很多问题。首先,Symfony在每个子类中插入一个私有的“预算”属性,以及getter和setter(这是对目的的继承)

/**
 * @var integer
 */
private $budget;

/**
 * Set budget
 *
 * @param integer $budget
 */
public function setBudget($budget)
{
    $this->budget = $budget;

    return $this;
}

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

其次,我遇到致命错误:

  

致命错误:MySite \ MainBundle \ Entity \ Drink :: $ budget的访问级别   必须是公共的(如在MySite \ MainBundle \ Entity \ BaseFoodType类中)   C:\ xampp \ htdocs \ MySite \ src \ MySite \ MainBundle \ Entity \ Drink.php在线   197

我可能会将生成的属性设为公开并且在我的路上,但同样,这会破坏继承的目的!

提前感谢任何见解。

2 个答案:

答案 0 :(得分:3)

Doctrine提供了指定生成字段可见性的方法。受保护或私人。默认为私有。

问题是调用Doctrine的Symfony命令无法改变它。

创建自己的标准Symfony命令的子类将允许您更好地控制生成过程。这可能会帮助你。

namespace Foo\Bundle\FooBundle\Command;

use Doctrine\Bundle\DoctrineBundle\Command as DC;
use Doctrine\ORM\Tools\EntityGenerator;

class GenerateEntitiesDoctrineCommand extends DC\GenerateEntitiesDoctrineCommand
{

    protected function configure()
    {
        parent::configure();
        $this->setName('foo:generate:entities');
    }

    /**
     * get a doctrine entity generator
     *
     * @return EntityGenerator
     */
    protected function getEntityGenerator()
    {
        $entityGenerator = new EntityGenerator();
        $entityGenerator->setGenerateAnnotations(true);
        $entityGenerator->setGenerateStubMethods(true);
        $entityGenerator->setRegenerateEntityIfExists(false);
        $entityGenerator->setUpdateEntityIfExists(true);
        $entityGenerator->setNumSpaces(4);
        $entityGenerator->setAnnotationPrefix('ORM\\');
        $entityGenerator->setFieldVisibility($entityGenerator::FIELD_VISIBLE_PROTECTED);

        return $entityGenerator;
    }
}

这有两件事。它将属性可见性设置为受保护。这可以防止php错误。

$entityGenerator->setFieldVisibility($entityGenerator::FIELD_VISIBLE_PROTECTED);

它还将映射超类中的注释复制到实体类中。

$entityGenerator->setGenerateAnnotations(true);

这是一些示例代码,其中属性从基类继承,并且它们的可见性和注释正确地复制到继承类中

/** @ORM\MappedSuperclass */
class DataSuper {
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\ManyToOne(targetEntity="Campaign", inversedBy="data")
     * @ORM\JoinColumn(name="campaign_id", referencedColumnName="id")
     * @Exclude
     */
    protected $campaign;

    /**
     * @ORM\Column(type="text", nullable=true, name="data")
     */
    protected $data;

    /**
     * @ORM\Column(type="datetime")
     */
    protected $createdDate;
}


/**
 * @ORM\Entity(repositoryClass="Foo\Bundle\FooBundle\Entity\DataRepository")
 * @ORM\Table(name="data")
 * @ExclusionPolicy("none")
 */
class Data extends DataSuper
{
}

生成后,Data类看起来像:

class Data extends DataSuper
{

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
protected $id;

/**
 * @var string
 *
 * @ORM\Column(name="data", type="text", precision=0, scale=0, nullable=true, unique=false)
 */
protected $data;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="createdDate", type="datetime", precision=0, scale=0, nullable=false, unique=false)
 */
protected $createdDate;

/**
 * @var \Foo\Bundle\FooBundle\Entity\Campaign
 *
 * @ORM\ManyToOne(targetEntity="Foo\Bundle\FooBundle\Entity\Campaign", inversedBy="data")
 * @ORM\JoinColumns({
 *   @ORM\JoinColumn(name="campaign_id", referencedColumnName="id", nullable=true)
 * })
 */
protected $campaign;


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

/**
 * Set data
 *
 * @param string $data
 * @return Data
 */
public function setData($data)
{
    $this->data = $data;

    return $this;
}

/**
 * Get data
 *
 * @return string 
 */
public function getData()
{
    return $this->data;
}

/**
 * Set createdDate
 *
 * @param \DateTime $createdDate
 * @return Data
 */
public function setCreatedDate($createdDate)
{
    $this->createdDate = $createdDate;

    return $this;
}

/**
 * Get createdDate
 *
 * @return \DateTime 
 */
public function getCreatedDate()
{
    return $this->createdDate;
}

/**
 * Set campaign
 *
 * @param \Foo\Bundle\FooBundle\Entity\Campaign $campaign
 * @return Data
 */
public function setCampaign(\Foo\Bundle\FooBundle\Entity\Campaign $campaign = null)
{
    $this->campaign = $campaign;

    return $this;
}

/**
 * Get campaign
 *
 * @return \Foo\Bundle\FooBundle\Entity\Campaign 
 */
public function getCampaign()
{
    return $this->campaign;
}
}

表格结构正确无误:

php app/console doctrine:schema:update --force

答案 1 :(得分:0)

由于BaseFoodType::budget公开属性而doctrine:generate:entities在您的Drink / Snack类中创建了私有属性,因此抛出了异常,因为它扩展了BaseFoodType (这不正确,但现在命令的工作方式)。

子类中的属性可见性只能是相同级别或更多自由(私有 - > protected - > public),但绝不会更具限制性。

生成getter / setter时,

doctrine:generate:entities没有考虑超类的公共属性,因为具有公共属性的实现是非标准的。

因此,您必须手动调整生成的类。

我建议使用私有/受保护的属性与getter& setter方法。