我正在使用ZF2和Doctrine2构建一个应用程序。ideia是有一个基本的应用程序实体(让我们称之为UserEntity)。
但在一个模块A中,我将有另一个类似UserEntity的实体,它将用新字段"升级"基本实体。以及另一个模块B,它将添加更多字段。
例如:
基本用户实体{受保护的$id;//。。。}
ModuleAUserEntity扩展了BaseUserEntity{受保护模块AId;}
ModuleBUserEntity扩展BaseUserEntity{受保护的模块BUserName;}
有没有可能,以某种方式,得到一个方法,这样当我调用UserEntity时,它会返回完整的、按模块升级的实体?例如:
用户实体{受保护的$id;//。。。受保护模块AId;受保护的模块BUserName;}
有没有其他方法可以实现这样的目标?实体"扩展"的可能性?
我有两种不同的方法:
1.第一个:
你应该看看:http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html
这是合法的,也是教条建议的做法。
2.第二个
如果你不想让条令扰乱数据库,你可以使用另一种方法:
- 创建一个定义所有类的公共行为的接口
- 编写基类,实现该行为
- 编写子类,实现接口,包含新方法,并包装基类的实例
- 您实现了接口中定义的方法,但由于它们已经在父类中实现,因此只需绕过对包装对象的调用
所以,你使用组合而不是继承来避免教条(可能还有你)得到疯狂的
为了对条令有一个真正干净的行为,我想象的数据库是:
- 具有父实体的表
- 具有子实体的表,包含
- 具有相关父实体id的外键(即父表中包含与之相关的值的行,因为子实体必须具有父字段和子字段)
- 所有额外的列
例如:
接口:
namespace DBALEntity;
interface IProfesional
{
public function setName($name);
public function getName();
public function getId();
}
父类:
namespace DBALEntity;
use DoctrineORMMapping as ORM;
use DBALEntityUserIUserAware;
/**
* Profesional
*
* @ORMTable(name="profesional")
* @ORMEntity
*/
class Profesional implements IProfesional
{
/**
* @var string
*
* @ORMColumn(name="name", type="string", length=45, nullable=true)
*/
private $name;
/**
* @var integer
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* Set nombre
*
* @param string $nombre
* @return Profesional
*/
public function setName($nombre)
{
$this->name = $nombre;
return $this;
}
/**
* Get nombre
*
* @return string
*/
public function getNombre()
{
return $this->name;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
}
子类:
namespace DBALEntity;
use DBALEntityUserIUserAware;
use DoctrineORMMapping as ORM;
/**
* Jugador
*
* @ORMTable(name="jugador")
* @ORMEntity(repositoryClass="DBALRepositoryJugadorRepository")
*/
class Player implements IProfesional
{
/**
* @var integer
*
* @ORMColumn(name="profesional_id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var Profesional
*
* @ORMOneToOne(targetEntity="Profesional")
* @ORMJoinColumns({
* @ORMJoinColumn(name="profesional_id", referencedColumnName="id", unique=true)
* })
*/
private $profesional;
/**
* Constructor: you create an empty Profesional,
so you are sure you will never use a reference to an in-existent object.
But anyways, if this is an entity loaded from the database by doctrine,
doctrine will fill that field whith an actual professional from the parent table,
based in the foreign key id
*/
public function __construct()
{
if(!isset($id)){
$this->profesional=new Profesional();
}
}
/**
* Set profesional
*
* @param Profesional $profesional
* @return Jugador
*/
public function setProfesional( Profesional $profesional = null)
{
$this->profesional = $profesional;
return $this;
}
/**
* Get profesional
*
* @return Profesional
*/
public function getProfesional()
{
return $this->profesional;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->profesional->getId();
}
///New fields, for instance:
/**
* @var integer
*
* @ORMColumn(name="height", type="integer", nullable=true)
*/
private $height;
public function getHeight()
{
return $this->height;
}
public function setHeight($h)
{
$this->height=$h;
}
}