0

我试图在 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 都继承自这个基类,但我在尝试使用教义: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;
}

其次,我遇到了一个致命错误:

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

我可能可以将生成的属性公开并在我的路上,但同样,这违背了继承的目的!

提前感谢您的任何见解。

4

2 回答 2

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

于 2014-02-11T02:52:55.443 回答
0

抛出异常是因为BaseFoodType::budget它是一个公共属性,并在扩展 BaseFoodType 的 Drink / Snack 类中doctrine:generate:entities创建了一个私有属性(这是不正确的,但该命令现在的工作方式)。

子类中的属性可见性只能是相同级别或更自由(私有 -> 受保护 -> 公共),但永远不会受到更多限制。

学说:生成:实体在生成 getter/setter 时没有考虑超类的公共属性,因为使用公共属性的实现是非标准的。

因此,您将不得不手动调整生成的类。

我建议将私有/受保护的属性与 getter 和 setter 结合使用。

于 2013-07-01T16:56:26.293 回答